int main(int argc, char *argv[])
{
SDL_Surface *screen, *screen2;
SDL_Event event;
SDL_Joystick *joystick;
rotentry *rot;
uint32_t i=0, prev_tick=SDL_GetTicks(), tick, is;
uint16_t rot_a, rot_s, *stats, *stats2, rot_r, frame_ms;
int8_t exit_key=0, rotate_left=0, rotate_right=0, thrust=0, time_down=0, time_up=0, crash=0;
uint8_t *screen32, ib, il;
float time_scale, time_factor, space_scale;
double cam_x, cam_y;
/*FONT*/
SDL_Surface *font_surf;
uint8_t *font;
/*END FONT*/
char *line1;
/*ROCKET*/
SDL_Surface *rocket_surf, *rocket_alpha;
uint16_t rocket_d;
uint8_t *rocketRGB, *rocket_scaled, *rocket_rot, rocket_power;
vector rocket;
float dbb, dbb2, dbc;
/*END ROCKET*/
/*STAR*/
star_t star[STAR_COUNT];
uint32_t cam_star_x, cam_star_y;
/*END STAR*/
body_t body[BODY_COUNT];
SDL_Init(SDL_INIT_EVERYTHING);
atexit(SDL_Quit);
joystick = SDL_JoystickOpen(0);
screen=SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE);
screen2 = IMG_Load("screen.png");
screen32 = calloc (320 * 240 * 4, sizeof(uint8_t));
SDL_ShowCursor(SDL_DISABLE);
rot=rot_lut_load(&rot_a, &rot_r, &rot_s); //load the rotation LUT
font_surf=IMG_Load("TinyFont.bmp");
font = surf2font(font_surf, 6, 8);
SDL_FreeSurface(font_surf);
line1 = calloc (54, sizeof(char));
body[0].surf=IMG_Load("earth131a.png"); //load sprite
body[1].surf=IMG_Load("moon37a.png"); //load sprite
body[0].letter_surf=IMG_Load("blueEa.png"); //load Earth's letter
body[1].letter_surf=IMG_Load("greyMa.png"); //load Moon's letter
for (ib=0; ib<BODY_COUNT; ib++)
{
SDL_LockSurface(body[ib].surf);
body[ib].RGB=RGBarray(body[ib].surf, &body[ib].diam, &body[ib].diam, &body[ib].power); //turn it into an array
SDL_FreeSurface(body[ib].surf);
body[ib].rot = calloc (body[ib].diam * body[ib].diam * 4, sizeof(uint8_t)); //turn it into an array
body[ib].scaled = scale2(body[ib].RGB, &body[ib].diam, &body[ib].diam, &body[ib].power);
free(body[ib].RGB);
body[ib].letter=RGBarray_np(body[ib].letter_surf, &body[ib].letter_w, &body[ib].letter_h);
free(body[ib].letter_surf);
}
rocket_surf=IMG_Load("rocket1.png"); //load sprite
SDL_LockSurface(rocket_surf);
rocketRGB=RGBarray(rocket_surf, &rocket_d, &rocket_d, &rocket_power); //turn it into an array
SDL_FreeSurface(rocket_surf);
rocket_alpha=IMG_Load("rocket1alpha.png"); //load alpha layer
SDL_LockSurface(rocket_alpha);
add_alpha(rocket_alpha, rocketRGB, rocket_d, rocket_power); //integrate the alpha layer
SDL_FreeSurface(rocket_alpha);
rocket_rot = calloc (rocket_d * rocket_d * 4, sizeof(uint8_t)); //turn it into an array
rocket_scaled = scale2(rocketRGB, &rocket_d, &rocket_d, &rocket_power);
free(rocketRGB);
for (is=0; is<STAR_COUNT; is++)
{
star[is].x = rand_u32()%STAR_FIELD_SIZE;
star[is].y = rand_u32()%STAR_FIELD_SIZE;
// star[is].mag = (rand_u32()%256)*(rand_u32()%256)*(rand_u32()%256)>>16;
star[is].mag = (rand_u32()%256)*(rand_u32()%256)>>8;
}
frame_ms = 20; //last frame duration in real world milliseconds
time_scale = 1; //unit = game seconds / real world seconds
time_factor = frame_ms * 0.001 * time_scale; //unit = seconds / frame
space_scale = 0.00001; //unit = 1 / (meter/pixel)
rocket.mass = 3038500; //3038500 kg
rocket.thrust = 34020000; //34.02 Mega Newtons
rocket.pos_x = 0; //meters
rocket.pos_y = -6678000; //meters
rocket.speed_x = -7730; //meters / second
rocket.speed_y = 0;
rocket.thrust_x = 0;
rocket.thrust_y = 0;
rocket.angle = 0;
body[0].pos_x = 0;
body[0].pos_y = 0;
body[0].speed_x = 12.13;
body[0].speed_y = 0;
body[0].mass = 3.98730056e14; //5.9742e24 * G (G = 6.6742e-11)
body[0].radius2 = 40680631590769.0; //6378137^2
body[0].angle = 0;
body[0].rot_spd = 0.000011605762776514406680156354228817; //1 / 86,164.091 seconds
body[0].link_count = 1;
body[0].linked_body_ID = calloc (body[0].link_count, sizeof(uint8_t));
body[0].linked_body_ID[0] = 1; //Earth is linked to Moon (ID 1)
body[1].pos_x = 0;
body[1].pos_y = -405696000; //meters (apogee)
body[1].speed_x = -986; //meters / second
body[1].speed_y = 0;
body[1].mass = 4.90400193e12; //7.3477e22 * G (G = 6.6742e-11)
body[1].radius2 = 3021130659600.0; //1738140^2
body[1].angle = 0;
body[1].rot_spd = 4.23623862e-7; //1 / 2,360,584.68 seconds
body[1].link_count = 1;
body[1].linked_body_ID = calloc (body[1].link_count, sizeof(uint8_t));
body[1].linked_body_ID[0] = 0; //Moon is linked to Earth (ID 0)
for (ib=0; ib<BODY_COUNT; ib++)
rotation(body[ib].scaled, body[ib].rot, body[ib].diam, rot, rot_s, body[ib].ia, rot_a, rot_r, body[ib].power);
rotation(rocket_scaled, rocket_rot, rocket_d, rot, rot_s, rocket.ia, rot_a, rot_r, rocket_power);
while (exit_key==0)
{
if (SDL_PollEvent(&event))
{
if (event.type==SDL_KEYDOWN)
switch (event.key.keysym.sym)
{
case SDLK_q:
exit_key=1;
break;
case SDLK_UP:
thrust=1;
break;
case SDLK_LEFT:
rotate_left=1;
break;
case SDLK_RIGHT:
rotate_right=1;
break;
case SDLK_KP7:
time_down=1;
break;
case SDLK_KP9:
time_up=1;
break;
}
if (event.type==SDL_KEYUP)
switch (event.key.keysym.sym)
{
case SDLK_UP:
thrust=0;
break;
case SDLK_LEFT:
rotate_left=0;
break;
case SDLK_RIGHT:
rotate_right=0;
break;
}
if (event.type==SDL_JOYBUTTONDOWN)
switch (event.jbutton.button)
{
case GPB_START:
exit_key=1;
break;
case GPB_UP:
thrust=1;
break;
case GPB_LEFT:
rotate_left=1;
break;
case GPB_RIGHT:
rotate_right=1;
break;
case GPB_L:
time_down=1;
break;
case GPB_R:
time_up=1;
break;
}
if (event.type==SDL_JOYBUTTONUP)
switch (event.jbutton.button)
{
case GPB_UP:
thrust=0;
break;
case GPB_LEFT:
rotate_left=0;
break;
case GPB_RIGHT:
rotate_right=0;
break;
}
}
/********************Physics********************/
tick = SDL_GetTicks();
frame_ms = tick - prev_tick;
prev_tick = tick;
sprintf(line1, "%d ms", frame_ms);
if (frame_ms>40) //frame duration capping
frame_ms = 40;
if (time_down==1)
{
time_scale*=0.5;
time_down=0;
}
if (time_up==1)
{
time_scale*=2;
time_up=0;
}
time_factor = frame_ms * 0.001 * time_scale;
if (rotate_left==1)
rocket.angle-=0.01;
if (rotate_right==1)
rocket.angle+=0.01;
if (thrust==1)
{
rocket.thrust_y = rocket.thrust * cosf(rocket.angle * pi * 2);
rocket.thrust_x = rocket.thrust * -sinf(rocket.angle * pi * 2);
}
else
{
rocket.thrust_y = 0;
rocket.thrust_x = 0;
}
rocket.angle = fmodf(rocket.angle, 1);
rocket.prev_ia = rocket.ia;
rocket.ia = nearbyint(rocket.angle * ((rot_a-1)<<2));
rocket.ia%=(rot_a-1)<<2;
/*N-body interactions start here*/
rocket.vect_y = 0;
rocket.vect_x = 0;
for (ib=0; ib<BODY_COUNT; ib++) //angles
{
body[ib].angle -= body[ib].rot_spd * time_factor;
body[ib].angle = fmodf(body[ib].angle, 1);
body[ib].prev_ia = body[ib].ia;
body[ib].ia = nearbyint(body[ib].angle * ((rot_a-1)<<2));
body[ib].ia%=(rot_a-1)<<2;
/*Inter-body interactions*/
body[ib].vect_y = 0;
body[ib].vect_x = 0;
for (il=0; il<body[ib].link_count; il++)
{
dbb2 = distance2(body[ib].pos_x, body[ib].pos_y, body[body[ib].linked_body_ID[il]].pos_x, body[body[ib].linked_body_ID[il]].pos_y); //distance body-body
dbb = sqrt(dbb2);
body[ib].vect_mag = time_factor * body[body[ib].linked_body_ID[il]].mass / dbb2;
body[ib].vect_y += (body[ib].vect_mag * (body[ib].pos_y - body[body[ib].linked_body_ID[il]].pos_y)) / dbb;
body[ib].vect_x += (body[ib].vect_mag * (body[ib].pos_x - body[body[ib].linked_body_ID[il]].pos_x)) / dbb;
}
body[ib].speed_y-=body[ib].vect_y; //meters / second
body[ib].speed_x-=body[ib].vect_x; //meters / second
body[ib].pos_y+=time_factor*body[ib].speed_y; //meters
body[ib].pos_x+=time_factor*body[ib].speed_x; //meters
/*Rocket-bodies interactions*/
dbb2 = distance2(body[ib].pos_x, body[ib].pos_y, rocket.pos_x, rocket.pos_y); //distance earth-rocket in meters
if (dbb2<body[ib].radius2)
crash=1;
dbb = sqrt(dbb2);
rocket.vect_mag = time_factor * body[ib].mass / dbb2;
rocket.vect_y += (rocket.vect_mag * (rocket.pos_y-body[ib].pos_y)) / dbb;
rocket.vect_x += (rocket.vect_mag * (rocket.pos_x-body[ib].pos_x)) / dbb;
}
if (crash==0)
{
rocket.speed_y-=rocket.thrust_y/rocket.mass + rocket.vect_y; //meters / second
rocket.speed_x-=rocket.thrust_x/rocket.mass + rocket.vect_x; //meters / second
rocket.pos_y+=time_factor*rocket.speed_y; //meters
rocket.pos_x+=time_factor*rocket.speed_x; //meters
}
/********************Graphics********************/
cam_x=rocket.pos_x;
cam_y=rocket.pos_y;
for (ib=0; ib<BODY_COUNT; ib++)
{
if (body[ib].ia!=body[ib].prev_ia)
rotation(body[ib].scaled, body[ib].rot, body[ib].diam, rot, rot_s, body[ib].ia, rot_a, rot_r, body[ib].power);
blit_center((uint32_t *)screen32, (uint32_t *)body[ib].rot, body[ib].diam>>rot_s, body[ib].diam>>rot_s, nearbyint((body[ib].pos_x-cam_x)*space_scale+160), nearbyint((body[ib].pos_y-cam_y)*space_scale+120), 0);
dbc = sqrt(distance2(body[ib].pos_x, body[ib].pos_y, cam_x, cam_y)*space_scale*space_scale);
if (dbc>200 && tick%(int)(dbc+200)>200)
blit_center((uint32_t *)screen32, (uint32_t *)body[ib].letter, body[ib].letter_w, body[ib].letter_h, nearbyint(((body[ib].pos_x-cam_x)*space_scale)/dbc*160+160), nearbyint(((body[ib].pos_y-cam_y)*space_scale)/dbc*120+120), 0);
}
if (rocket.ia!=rocket.prev_ia)
rotation(rocket_scaled, rocket_rot, rocket_d, rot, rot_s, rocket.ia, rot_a, rot_r, rocket_power);
blit_center((uint32_t *)screen32, (uint32_t *)rocket_rot, rocket_d>>rot_s, rocket_d>>rot_s, nearbyint((rocket.pos_x-cam_x)*space_scale+160), nearbyint((rocket.pos_y-cam_y)*space_scale+120), 1);
cam_star_y = (uint32_t) nearbyint(cam_y*space_scale*192);
cam_star_x = (uint32_t) nearbyint(cam_x*space_scale*192);
for (is=0; is<STAR_COUNT; is++)
star_blit(screen32, (star[is].x-cam_star_x)%STAR_FIELD_SIZE, (star[is].y-cam_star_y)%STAR_FIELD_SIZE, star[is].mag);
text_blit((uint32_t *)screen32, line1, font, 6, 8, 0, 232);
/********************SDL Blitting********************/
surf_array_o(screen2, screen32, 320, 240);
SDL_UnlockSurface(screen2);
SDL_BlitSurface(screen2, NULL, screen, NULL);
SDL_Flip(screen);
SDL_Delay(10);
SDL_LockSurface(screen2);
zeroarray((uint32_t *)screen32, 76800); //76800 = 320 * 240
}
printf("Distance : %.3f AU", sqrt(distance2(0, 0, rocket.pos_x, rocket.pos_y))/150000000000.0);
SDL_FreeSurface(screen);
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
return 0;
}