[Add] Vec2 now uses polor coords.

This commit is contained in:
Allanis 2013-02-02 22:52:58 +00:00
parent bf4b1fb02a
commit a7546372cc
7 changed files with 128 additions and 79 deletions

View File

@ -121,6 +121,10 @@ int main(int argc, char** argv) {
else if(strcmp(str, "keyboard")==0) type = KEYBIND_KEYBOARD; else if(strcmp(str, "keyboard")==0) type = KEYBIND_KEYBOARD;
else if(strcmp(str, "jaxis")==0) type = KEYBIND_JAXIS; else if(strcmp(str, "jaxis")==0) type = KEYBIND_JAXIS;
else if(strcmp(str, "jbutton")==0) type = KEYBIND_JBUTTON; else if(strcmp(str, "jbutton")==0) type = KEYBIND_JBUTTON;
else {
WARN("Unknown keybinding of type %s", str);
continue;
}
// Set the keybind. // Set the keybind.
input_setKeybind((char*)keybindNames[i], type, key, reverse); input_setKeybind((char*)keybindNames[i], type, key, reverse);
} else WARN("Malformed keybind in %s", CONF_FILE); } else WARN("Malformed keybind in %s", CONF_FILE);
@ -239,9 +243,11 @@ static void update_all(void) {
time = SDL_GetTicks(); time = SDL_GetTicks();
if(dt > MINIMUM_FPS) { 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."); gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
return;
} }
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@ -266,7 +272,8 @@ static void display_fps(const double dt) {
fps = fps_cur / fps_dt; fps = fps_cur / fps_dt;
fps_dt = fps_cur = 0.; 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); gl_print(NULL, &pos, "%3.2f", fps);
} }

View File

@ -233,8 +233,8 @@ void gl_freeTexture(gl_texture* texture) {
// Blit the sprite at given position. // Blit the sprite at given position.
void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy) { 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. // Don't bother drawing if offscreen -- waste of cycles.
if(fabs(pos->x - gl_camera->x) > gl_screen.w / 2 + sprite->sw / 2 || if(fabs(VX(*pos) -VX(*gl_camera)) > gl_screen.w / 2 + sprite->sw / 2 ||
fabs(pos->y-gl_camera->y) > gl_screen.h / 2 + sprite->sh / 2) fabs(VY(*pos) -VY(*gl_camera)) > gl_screen.h / 2 + sprite->sh / 2)
return; return;
glEnable(GL_TEXTURE_2D); 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); glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Projection translation matrix. glPushMatrix(); // Projection translation matrix.
glTranslated(pos->x - gl_camera->x - sprite->sw/2., glTranslated(VX(*pos) -VX(*gl_camera) - sprite->sw/2.,
pos->y - gl_camera->y - sprite->sh/2., 0.); VY(*pos) -VY(*gl_camera) - sprite->sh/2., 0.);
glScalef((double)gl_screen.w/SCREEN_W, (double)gl_screen.h/SCREEN_H, 0.); glScalef((double)gl_screen.w/SCREEN_W, (double)gl_screen.h/SCREEN_H, 0.);
// Actual blitting.... // Actual blitting....
@ -276,7 +276,7 @@ void gl_blitStatic(const gl_texture* texture, const Vec2* pos) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Set up translation matrix. 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.); glScaled((double)gl_screen.w/SCREEN_W, (double)gl_screen.h/SCREEN_H, 0.);
// Actual blitting.. // Actual blitting..
@ -327,7 +327,7 @@ void gl_print(const gl_font* ft_font, const Vec2* pos, const char* fmt, ...) {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); // Translation matrix. 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.); glColor4d(1., 1., 1., 1.);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, &text); glCallLists(strlen(text), GL_UNSIGNED_BYTE, &text);

View File

@ -8,9 +8,17 @@
#define M_PI 3.14159265358979323846f #define M_PI 3.14159265358979323846f
#endif #endif
// Pretty efficient, no need for sine table!! // Init cartesian vector.
#define SIN(dir)(sinf(dir)) void vect_cinit(Vec2* v, double x, double y) {
#define COS(dir)(cosf(dir)) 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.======================================== // ==Update method.========================================
// d^2 x(t) / d t^2 = a, a = constant (acceleration) // 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 // Since dt isn't actually differential this gives us an
// error, so watch out with big values for dt. // 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) { static void simple_update(Solid* obj, const double dt) {
// Make sure angle doesn't flip. // 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 > 2*M_PI) obj->dir -= 2*M_PI;
if(obj->dir < 0.0) obj->dir += 2*M_PI; if(obj->dir < 0.) obj->dir += 2*M_PI;
if(obj->force) {
Vec2 acc; double px, py, vx, vy;
acc.x = obj->force / obj->mass * COS(obj->dir); px = VX(obj->pos);
acc.y = obj->force / obj->mass * SIN(obj->dir); py = VY(obj->pos);
vx = VX(obj->vel);
vy = VY(obj->vel);
obj->pos.x += acc.x * dt; if(obj->force.mod) { // Force applied on an object.
obj->vel.y += acc.y * dt; 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; vx += ax*dt;
obj->pos.y += obj->vel.y * dt + 0.5 * acc.y * dt*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 { } else {
obj->pos.x += obj->vel.x * dt; px += vx*dt;
obj->pos.y += obj->vel.y * dt; py += vy*dt;
} }
obj->pos.mod = MOD(px, py);
obj->pos.angle = ANGLE(px, py);
} }
#endif #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) // 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) { static void rk4_update(Solid* obj, const double dt) {
// Make sure angle doesn't flip. // Make sure angle doesn't flip.
obj->dir += obj->dir_vel/360.0*dt; obj->dir += obj->dir_vel/360.0*dt;
if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI; if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI;
if(obj->dir < 0.0) 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; int i;
Vec2 initial, tmp; double ix, iy, tx, ty; // Initial and temp cartesian vector values.
Vec2 acc; double ax, ay;
acc.x = obj->force / obj->mass * COS(obj->dir); ax = VX(obj->force)/obj->mass;
acc.y = obj->force / obj->mass * SIN(obj->dir); ay = VY(obj->force)/obj->mass;
for(i = 0; i < N; i++) {
for(i = 0; i < RK4_N; i++) {
// X component. // X component.
tmp.x = initial.x = obj->vel.x; tx = ix = vx;
tmp.x += 2*initial.x + h*tmp.x; tx += 2*ix + h*tx;
tmp.x += 2*initial.x + h*tmp.x; tx += 2*ix + h*tx;
tmp.x += initial.x + h*tmp.x; tx += ix + h*tx;
tmp.x *= h/6; tx *= h/6;
obj->pos.x += tmp.x; px += tx;
obj->vel.x += acc.x*h; vx += ax*h;
// Y component. // Y component.
tmp.y = initial.y = obj->vel.y; ty = iy = vy;
tmp.y += 2*(initial.y + h/2*tmp.y); ty += 2*(iy + h/2*ty);
tmp.y += 2*(initial.y + h/2*tmp.y); ty += 2*(iy + h/2*ty);
tmp.y += initial.y + h*tmp.y; ty += iy +h*ty;
tmp.y *= h/6; ty *= h/6;
obj->pos.y += tmp.y; py += ty;
obj->pos.y += acc.y*h; vy += ay*h;
} }
obj->vel.mod = MOD(vx, vy);
obj->vel.angle = ANGLE(vx, vy);
} else { } else {
obj->pos.x += dt*obj->vel.x; px += dt*vx;
obj->pos.y += dt*obj->vel.y; py += dt*vy;
} }
obj->pos.mod = MOD(px, py);
obj->pos.angle = ANGLE(px, py);
} }
// Initialize a new solid. // Initialize a new solid.
void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos) { void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos) {
dest->mass = mass; dest->mass = mass;
dest->force = 0; dest->force.mod = 0;
dest->dir = 0; dest->dir = 0;
if(vel == NULL) if(vel == NULL)
dest->vel.x = dest->vel.y = 0.0; vect_cinit(&dest->vel, 0., 0.);
else { else
dest->vel.x = vel->x; vect_pinit(&dest->vel, vel->mod, vel->angle);
dest->vel.y = vel->y;
}
if(pos == NULL) if(pos == NULL)
dest->pos.x = dest->pos.y = 0.0; vect_cinit(&dest->pos, 0., 0.);
else { else
dest->pos.x = pos->x; vect_pinit(&dest->pos, pos->mod, pos->angle);
dest->pos.y = pos->y;
}
dest->update = rk4_update; dest->update = rk4_update;
//dest->update = simple_update;
} }
// Create a new solid. // Create a new solid.

View File

@ -1,20 +1,33 @@
#pragma once #pragma once
#include "def.h" #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. // Base of 2D vectors.
typedef struct { typedef struct {
double x, y; // Basic 2D vector components. double mod, angle; // Basic 2D vector components.
} Vec2; } 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. // Describe any solid in 2D space.
struct Solid { struct Solid {
double mass, force, dir, dir_vel; // Properties. double mass, dir, dir_vel; // Properties.
Vec2 vel, pos; // Position/velocity vectors. Vec2 vel, pos, force; // Position/velocity vectors.
void(*update)(struct Solid*, const double); // Update method. void(*update)(struct Solid*, const double); // Update method.
}; };
typedef struct Solid Solid; typedef struct Solid Solid;
// Solid manipulation.
void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos); 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); Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos);
void solid_free(Solid* src); void solid_free(Solid* src);

View File

@ -7,9 +7,6 @@
#include "log.h" #include "log.h"
#include "pilot.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. // Stack of pilot id's to assure uniqueness.
static unsigned int pilot_id = 0; static unsigned int pilot_id = 0;
@ -57,8 +54,9 @@ static void pilot_update(Pilot* pilot, const double dt) {
// Update the solid. // Update the solid.
pilot->solid->update(pilot->solid, dt); 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. // Should not go faster.
VMOD(pilot->solid->vel) = pilot->ship->speed;
} }
pilot_render(pilot); pilot_render(pilot);

View File

@ -29,7 +29,8 @@ void player_think(Pilot* player, const double dt) {
if(player_turn) if(player_turn)
player->solid->dir_vel -= player->ship->turn * 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). // Initialization/exit functions (does not assign keys).

View File

@ -1,3 +1,6 @@
#include <malloc.h>
#include <math.h>
#include "log.h" #include "log.h"
#include "physics.h" #include "physics.h"
#include "opengl.h" #include "opengl.h"
@ -7,7 +10,7 @@
#define STAR_BUF 100 // Area to leave around screen. #define STAR_BUF 100 // Area to leave around screen.
typedef struct { typedef struct {
Vec2 pos; double x, y;
double brightness; double brightness;
} Star; } Star;
@ -20,8 +23,8 @@ void space_init(void) {
stars = malloc(sizeof(Star)*nstars); stars = malloc(sizeof(Star)*nstars);
for(i = 0; i < nstars; i++) { for(i = 0; i < nstars; i++) {
stars[i].brightness = (double)RNG(50, 200)/256.; stars[i].brightness = (double)RNG(50, 200)/256.;
stars[i].pos.x = (double)RNG(-STAR_BUF, gl_screen.w + STAR_BUF); stars[i].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].y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF);
} }
} }
@ -33,16 +36,16 @@ void space_render(double dt) {
glBegin(GL_POINTS); glBegin(GL_POINTS);
for(i = 0; i < nstars; i++) { for(i = 0; i < nstars; i++) {
// Update the position. // Update the position.
stars[i].pos.x -= player->solid->vel.x/(15.-10.*stars[i].brightness)*dt; stars[i].x -= VX(player->solid->vel)/(15.-10.*stars[i].brightness)*dt;
stars[i].pos.y -= player->solid->vel.y/(15.-10.*stars[i].brightness)*dt; stars[i].y -= VY(player->solid->vel)/(15.-10.*stars[i].brightness)*dt;
// Scroll those stars bitch! // Scroll those stars bitch!
if(stars[i].pos.x > gl_screen.w + STAR_BUF) stars[i].pos.x = -STAR_BUF; if(stars[i].x > gl_screen.w + STAR_BUF) stars[i].x = -STAR_BUF;
else if(stars[i].pos.x < -STAR_BUF) stars[i].pos.x = gl_screen.w + STAR_BUF; else if(stars[i].x < -STAR_BUF) stars[i].x = gl_screen.w + STAR_BUF;
if(stars[i].pos.y > gl_screen.h + STAR_BUF) stars[i].pos.y = -STAR_BUF; if(stars[i].y > gl_screen.h + STAR_BUF) stars[i].y = -STAR_BUF;
else if(stars[i].pos.y < -STAR_BUF) stars[i].pos.y = gl_screen.h + STAR_BUF; else if(stars[i].y < -STAR_BUF) stars[i].y = gl_screen.h + STAR_BUF;
// Render. // Render.
glColor4d(1., 1., 1., stars[i].brightness); glColor4d(1., 1., 1., stars[i].brightness);
glVertex2d(stars[i].pos.x, stars[i].pos.y); glVertex2d(stars[i].x, stars[i].y);
} }
glEnd(); glEnd();
glPopMatrix(); // Projection translation matrix. glPopMatrix(); // Projection translation matrix.