diff --git a/src/main.c b/src/main.c index fc187ae..abb5b25 100644 --- a/src/main.c +++ b/src/main.c @@ -121,6 +121,10 @@ int main(int argc, char** argv) { else if(strcmp(str, "keyboard")==0) type = KEYBIND_KEYBOARD; else if(strcmp(str, "jaxis")==0) type = KEYBIND_JAXIS; else if(strcmp(str, "jbutton")==0) type = KEYBIND_JBUTTON; + else { + WARN("Unknown keybinding of type %s", str); + continue; + } // Set the keybind. input_setKeybind((char*)keybindNames[i], type, key, reverse); } else WARN("Malformed keybind in %s", CONF_FILE); @@ -239,9 +243,11 @@ static void update_all(void) { time = SDL_GetTicks(); if(dt > MINIMUM_FPS) { - Vec2 pos = { .x = 10., .y = gl_screen.h-40 }; + Vec2 pos; + vect_cinit(&pos, 10., (double)(gl_screen.h-40)); gl_print(NULL, &pos, "FPS is really low! Skipping frames."); SDL_GL_SwapBuffers(); + return; } glClear(GL_COLOR_BUFFER_BIT); @@ -266,7 +272,8 @@ static void display_fps(const double dt) { fps = fps_cur / fps_dt; fps_dt = fps_cur = 0.; } - Vec2 pos = { .x = 10., .y = (double)(gl_screen.h-20) }; + Vec2 pos; + vect_cinit(&pos, 10., (double)(gl_screen.h-20)); gl_print(NULL, &pos, "%3.2f", fps); } diff --git a/src/opengl.c b/src/opengl.c index 4807528..63b9ab6 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -233,8 +233,8 @@ void gl_freeTexture(gl_texture* texture) { // Blit the sprite at given position. void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy) { // Don't bother drawing if offscreen -- waste of cycles. - if(fabs(pos->x - gl_camera->x) > gl_screen.w / 2 + sprite->sw / 2 || - fabs(pos->y-gl_camera->y) > gl_screen.h / 2 + sprite->sh / 2) + if(fabs(VX(*pos) -VX(*gl_camera)) > gl_screen.w / 2 + sprite->sw / 2 || + fabs(VY(*pos) -VY(*gl_camera)) > gl_screen.h / 2 + sprite->sh / 2) return; glEnable(GL_TEXTURE_2D); @@ -245,8 +245,8 @@ void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, cons glMatrixMode(GL_PROJECTION); glPushMatrix(); // Projection translation matrix. - glTranslated(pos->x - gl_camera->x - sprite->sw/2., - pos->y - gl_camera->y - sprite->sh/2., 0.); + glTranslated(VX(*pos) -VX(*gl_camera) - sprite->sw/2., + VY(*pos) -VY(*gl_camera) - sprite->sh/2., 0.); glScalef((double)gl_screen.w/SCREEN_W, (double)gl_screen.h/SCREEN_H, 0.); // Actual blitting.... @@ -276,7 +276,7 @@ void gl_blitStatic(const gl_texture* texture, const Vec2* pos) { glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPushMatrix(); // Set up translation matrix. - glTranslated(pos->x - (double)gl_screen.w/2., pos->y - (double)gl_screen.h/2., 0); + glTranslated(VX(*pos) - (double)gl_screen.w/2., VY(*pos) - (double)gl_screen.h/2., 0); glScaled((double)gl_screen.w/SCREEN_W, (double)gl_screen.h/SCREEN_H, 0.); // Actual blitting.. @@ -327,7 +327,7 @@ void gl_print(const gl_font* ft_font, const Vec2* pos, const char* fmt, ...) { glMatrixMode(GL_PROJECTION); glPushMatrix(); // Translation matrix. - glTranslated(pos->x - (double)gl_screen.w/2., pos->y - (double)gl_screen.h/2., 0); + glTranslated(VX(*pos) - (double)gl_screen.w/2., VY(*pos) - (double)gl_screen.h/2., 0); glColor4d(1., 1., 1., 1.); glCallLists(strlen(text), GL_UNSIGNED_BYTE, &text); diff --git a/src/physics.c b/src/physics.c index a32fa3c..7bc523d 100644 --- a/src/physics.c +++ b/src/physics.c @@ -8,9 +8,17 @@ #define M_PI 3.14159265358979323846f #endif -// Pretty efficient, no need for sine table!! -#define SIN(dir)(sinf(dir)) -#define COS(dir)(cosf(dir)) +// Init cartesian vector. +void vect_cinit(Vec2* v, double x, double y) { + v->mod = MOD(x,y); + v->angle = ANGLE(x, y); +} + +// Init polarized vector +void vect_pinit(Vec2* v, double mod, double angle) { + v->mod = mod; + v->angle = angle; +} // ==Update method.======================================== // d^2 x(t) / d t^2 = a, a = constant (acceleration) @@ -22,26 +30,38 @@ // Since dt isn't actually differential this gives us an // error, so watch out with big values for dt. // ======================================================== -#if 0 +#if 0 // Simply commenting this out to avoid silly warnings. static void simple_update(Solid* obj, const double dt) { // Make sure angle doesn't flip. - obj->dir += obj->dir_vel/360.0*dt; + obj->dir += obj->dir_vel/360.*dt; if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI; - if(obj->dir < 0.0) obj->dir += 2*M_PI; - if(obj->force) { - Vec2 acc; - acc.x = obj->force / obj->mass * COS(obj->dir); - acc.y = obj->force / obj->mass * SIN(obj->dir); + if(obj->dir < 0.) obj->dir += 2*M_PI; + + double px, py, vx, vy; + px = VX(obj->pos); + py = VY(obj->pos); + vx = VX(obj->vel); + vy = VY(obj->vel); - obj->pos.x += acc.x * dt; - obj->vel.y += acc.y * dt; + if(obj->force.mod) { // Force applied on an object. + double ax, ay; + ax = VX(obj->force)/obj->mass; + ay = VY(obj->force)/obj->mass; - obj->pos.x += obj->vel.x * dt + 0.5 * acc.x * dt*dt; - obj->pos.y += obj->vel.y * dt + 0.5 * acc.y * dt*dt; + vx += ax*dt; + vy += ay*dt; + + px += vx*dt + 0.5*ax * dt*dt; + py += vy*dt + 0.5*ay * dt*dt; + + obj->vel.mod = MOD(vx, vy); + obj->vel.angle = ANGLE(vx, vy); } else { - obj->pos.x += obj->vel.x * dt; - obj->pos.y += obj->vel.y * dt; + px += vx*dt; + py += vy*dt; } + obj->pos.mod = MOD(px, py); + obj->pos.angle = ANGLE(px, py); } #endif @@ -60,72 +80,79 @@ static void simple_update(Solid* obj, const double dt) { // x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a) // ======================================================== -#define RK4_N 4 +#define RK4_MIN_H 0.01 // Minimal pass we want. static void rk4_update(Solid* obj, const double dt) { // Make sure angle doesn't flip. obj->dir += obj->dir_vel/360.0*dt; if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI; if(obj->dir < 0.0) obj->dir += 2*M_PI; - double h = dt / RK4_N; // Step. + int N = (dt > RK4_MIN_H) ? (int)(dt/RK4_MIN_H) : 1; + double h = dt / (double)N; // Step. - if(obj->force) { // Force applied on object. + double px, py, vx, vy; + px = VX(obj->pos); + py = VY(obj->pos); + vx = VX(obj->vel); + vy = VY(obj->vel); + + if(obj->force.mod) { // Force applied on object. int i; - Vec2 initial, tmp; + double ix, iy, tx, ty; // Initial and temp cartesian vector values. - Vec2 acc; - acc.x = obj->force / obj->mass * COS(obj->dir); - acc.y = obj->force / obj->mass * SIN(obj->dir); - - for(i = 0; i < RK4_N; i++) { + double ax, ay; + ax = VX(obj->force)/obj->mass; + ay = VY(obj->force)/obj->mass; + for(i = 0; i < N; i++) { // X component. - tmp.x = initial.x = obj->vel.x; - tmp.x += 2*initial.x + h*tmp.x; - tmp.x += 2*initial.x + h*tmp.x; - tmp.x += initial.x + h*tmp.x; - tmp.x *= h/6; + tx = ix = vx; + tx += 2*ix + h*tx; + tx += 2*ix + h*tx; + tx += ix + h*tx; + tx *= h/6; - obj->pos.x += tmp.x; - obj->vel.x += acc.x*h; + px += tx; + vx += ax*h; // Y component. - tmp.y = initial.y = obj->vel.y; - tmp.y += 2*(initial.y + h/2*tmp.y); - tmp.y += 2*(initial.y + h/2*tmp.y); - tmp.y += initial.y + h*tmp.y; - tmp.y *= h/6; + ty = iy = vy; + ty += 2*(iy + h/2*ty); + ty += 2*(iy + h/2*ty); + ty += iy +h*ty; + ty *= h/6; - obj->pos.y += tmp.y; - obj->pos.y += acc.y*h; + py += ty; + vy += ay*h; } + obj->vel.mod = MOD(vx, vy); + obj->vel.angle = ANGLE(vx, vy); } else { - obj->pos.x += dt*obj->vel.x; - obj->pos.y += dt*obj->vel.y; + px += dt*vx; + py += dt*vy; } + obj->pos.mod = MOD(px, py); + obj->pos.angle = ANGLE(px, py); } // Initialize a new solid. void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos) { dest->mass = mass; - dest->force = 0; - dest->dir = 0; + dest->force.mod = 0; + dest->dir = 0; if(vel == NULL) - dest->vel.x = dest->vel.y = 0.0; - else { - dest->vel.x = vel->x; - dest->vel.y = vel->y; - } + vect_cinit(&dest->vel, 0., 0.); + else + vect_pinit(&dest->vel, vel->mod, vel->angle); if(pos == NULL) - dest->pos.x = dest->pos.y = 0.0; - else { - dest->pos.x = pos->x; - dest->pos.y = pos->y; - } + vect_cinit(&dest->pos, 0., 0.); + else + vect_pinit(&dest->pos, pos->mod, pos->angle); dest->update = rk4_update; + //dest->update = simple_update; } // Create a new solid. diff --git a/src/physics.h b/src/physics.h index fab782a..ec0645c 100644 --- a/src/physics.h +++ b/src/physics.h @@ -1,20 +1,33 @@ #pragma once #include "def.h" +#define VX(v) ((v).mod*cos((v).angle)) +#define VY(v) ((v).mod*sin((v).angle)) +#define VMOD(v) ((v).mod) +#define VANGLE(v) ((v).angle) + +#define MOD(x,y) (sqrt(x*x + y*y)) +#define ANGLE(x,y)((x==0.) ? 0. : ((x<0.)?atan(y/x)+M_PI:atan(y/x))) + // Base of 2D vectors. typedef struct { - double x, y; // Basic 2D vector components. + double mod, angle; // Basic 2D vector components. } Vec2; +// Vector manupulation. +void vect_cinit(Vec2* v, double x, double y); +void vect_pinit(Vec2* v, double mod, double angle); + // Describe any solid in 2D space. struct Solid { - double mass, force, dir, dir_vel; // Properties. - Vec2 vel, pos; // Position/velocity vectors. + double mass, dir, dir_vel; // Properties. + Vec2 vel, pos, force; // Position/velocity vectors. void(*update)(struct Solid*, const double); // Update method. }; typedef struct Solid Solid; +// Solid manipulation. void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos); Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos); void solid_free(Solid* src); diff --git a/src/pilot.c b/src/pilot.c index 37737d9..5440ff3 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -7,9 +7,6 @@ #include "log.h" #include "pilot.h" -#define VMOD(v) (v.x*v.x + v.y*v.y) -#define NMOD(n) (n*n) - // Stack of pilot id's to assure uniqueness. static unsigned int pilot_id = 0; @@ -57,8 +54,9 @@ static void pilot_update(Pilot* pilot, const double dt) { // Update the solid. pilot->solid->update(pilot->solid, dt); - if(VMOD(pilot->solid->vel) > NMOD(pilot->ship->speed)) { + if(VMOD(pilot->solid->vel) > pilot->ship->speed) { // Should not go faster. + VMOD(pilot->solid->vel) = pilot->ship->speed; } pilot_render(pilot); diff --git a/src/player.c b/src/player.c index 161a641..56a2841 100644 --- a/src/player.c +++ b/src/player.c @@ -29,7 +29,8 @@ void player_think(Pilot* player, const double dt) { if(player_turn) player->solid->dir_vel -= player->ship->turn * player_turn; - player->solid->force = player->ship->thrust * player_acc; + player->solid->force.angle = player->solid->dir; + player->solid->force.mod = player->ship->thrust * player_acc; } // Initialization/exit functions (does not assign keys). diff --git a/src/space.c b/src/space.c index 0a372b5..f92ab51 100644 --- a/src/space.c +++ b/src/space.c @@ -1,3 +1,6 @@ +#include +#include + #include "log.h" #include "physics.h" #include "opengl.h" @@ -7,7 +10,7 @@ #define STAR_BUF 100 // Area to leave around screen. typedef struct { - Vec2 pos; + double x, y; double brightness; } Star; @@ -20,8 +23,8 @@ void space_init(void) { stars = malloc(sizeof(Star)*nstars); for(i = 0; i < nstars; i++) { stars[i].brightness = (double)RNG(50, 200)/256.; - stars[i].pos.x = (double)RNG(-STAR_BUF, gl_screen.w + STAR_BUF); - stars[i].pos.y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF); + stars[i].x = (double)RNG(-STAR_BUF, gl_screen.w + STAR_BUF); + stars[i].y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF); } } @@ -33,16 +36,16 @@ void space_render(double dt) { glBegin(GL_POINTS); for(i = 0; i < nstars; i++) { // Update the position. - stars[i].pos.x -= player->solid->vel.x/(15.-10.*stars[i].brightness)*dt; - stars[i].pos.y -= player->solid->vel.y/(15.-10.*stars[i].brightness)*dt; + stars[i].x -= VX(player->solid->vel)/(15.-10.*stars[i].brightness)*dt; + stars[i].y -= VY(player->solid->vel)/(15.-10.*stars[i].brightness)*dt; // Scroll those stars bitch! - if(stars[i].pos.x > gl_screen.w + STAR_BUF) stars[i].pos.x = -STAR_BUF; - else if(stars[i].pos.x < -STAR_BUF) stars[i].pos.x = gl_screen.w + STAR_BUF; - if(stars[i].pos.y > gl_screen.h + STAR_BUF) stars[i].pos.y = -STAR_BUF; - else if(stars[i].pos.y < -STAR_BUF) stars[i].pos.y = gl_screen.h + STAR_BUF; + if(stars[i].x > gl_screen.w + STAR_BUF) stars[i].x = -STAR_BUF; + else if(stars[i].x < -STAR_BUF) stars[i].x = gl_screen.w + STAR_BUF; + if(stars[i].y > gl_screen.h + STAR_BUF) stars[i].y = -STAR_BUF; + else if(stars[i].y < -STAR_BUF) stars[i].y = gl_screen.h + STAR_BUF; // Render. glColor4d(1., 1., 1., stars[i].brightness); - glVertex2d(stars[i].pos.x, stars[i].pos.y); + glVertex2d(stars[i].x, stars[i].y); } glEnd(); glPopMatrix(); // Projection translation matrix.