X-Git-Url: http://deadsoftware.ru/gitweb?p=netwar.git;a=blobdiff_plain;f=game.c;h=2370692abdad4904825a910b65828b03821394a3;hp=cbc8e156ce5ff24ec6ef70e1a9150f34052f8a3d;hb=HEAD;hpb=c4b04d12861ae0eac6315b1c2170013422136f80 diff --git a/game.c b/game.c index cbc8e15..2370692 100644 --- a/game.c +++ b/game.c @@ -6,26 +6,24 @@ #include "game.h" -#define SPEED 0.00006 -#define ROTATE 0.00004 +#define SPEED (0.0005 / TICK) +#define ROTATE (0.03 / TICK) +#define BULL_SPEED (0.4 / TICK) -Player g_player[MAX_PLAYERS]; +#define MAX_SPEED (0.1 / TICK) +#define MAX_ROTATE (0.3 / TICK) -static void moveplayer(int id, float speed) { - g_player[id].vx += speed * cos(g_player[id].r * 2 * M_PI); - g_player[id].vy += speed * sin(g_player[id].r * 2 * M_PI); -} +// Цифры взяты с потолка, но вроде неплохо подобраны +#define G 6.6719199e-11 +#define M_STAR 3e8 +#define M_SHIP 0.001 -static void checkspacebound(float * a) { - float x = *a; - if(x < -1) - x = abs(x); - else if(x > 1) - x = -x; - *a = x; -} +Player g_player[MAX_PLAYERS]; +Bullet g_bullet[MAX_BULLETS]; + +static bool svmode; -void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr) { +void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr, int shoot) { assert(id < MAX_PLAYERS); g_player[id] = (Player) { .updated = true, @@ -39,18 +37,92 @@ void g_player_set(unsigned int id, bool live, float x, float y, float r, float v }; } -void g_player_does(unsigned int id, DoesCode code) { - assert(id < MAX_PLAYERS); - g_player[id].updated = true; - switch(code) { - case DOES_UP: moveplayer(id, SPEED); break; - case DOES_DOWN: moveplayer(id, -SPEED); break; - case DOES_LEFT: g_player[id].vr -= ROTATE; break; - case DOES_RIGHT: g_player[id].vr += ROTATE; break; - case DOES_FIRE: break; +void g_bullet_set(unsigned int id, unsigned int owner, bool live, float x, float y, float vx, float vy, int tick) { + assert(id < MAX_BULLETS); + assert(owner < MAX_PLAYERS); + g_bullet[id] = (Bullet) { + .live = live, + .owner = owner, + .x = x, + .y = y, + .vx = vx, + .vy = vy, + .tick = tick, + }; +} + +static int freebullet() { + for(int i = 0; i < MAX_BULLETS; i++) + if(!g_bullet[i].live) + return i; + return -1; +} + +static void moveplayer(int id, float speed) { + if(fabs(g_player[id].vx) < MAX_SPEED) + g_player[id].vx += speed * cos(g_player[id].r * 2 * M_PI); + if(fabs(g_player[id].vy) < MAX_SPEED) + g_player[id].vy += speed * sin(g_player[id].r * 2 * M_PI); +} + +static void roteplayer(int id, float speed) { + g_player[id].vr += speed; + if(fabs(g_player[id].vr) > MAX_ROTATE) + g_player[id].vr = copysignf(MAX_ROTATE, g_player[id].vr); +} + +static void fireplayer(int id) { + int j = freebullet(); + if(j < 0) + return; + + if(g_player[id].shoot < PLAYER_SHOOT) + return; + + g_player[id].shoot = 0; + + if(svmode) { + float vx = BULL_SPEED * cos(g_player[id].r * 2 * M_PI); + float vy = BULL_SPEED * sin(g_player[id].r * 2 * M_PI); + g_bullet_set(j, id, true, g_player[id].x, g_player[id].y, vx, vy, 0); } } +static void checkspacebound(float * a) { + float x = *a; + if(x < -1 || x > 1) + x = copysign(fmodf(x, 1) + 1, -1 * x); + *a = x; +} + +static float length(float x1, float y1, float x2, float y2) { + return sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2)); +} + +static bool collide(float x1, float y1, float r1, float x2, float y2, float r2) { + return ((length(x1, y1, x2, y2) - r1 - r2) <= 0); +} + +static void gravity(float * vx, float * vy, float x, float y) { + *vx += copysign(G * M_STAR * M_SHIP / length(0, 0, x, y), x * -1); + *vy += copysign(G * M_STAR * M_SHIP / length(0, 0, x, y), y * -1); +} + +void g_player_does(unsigned int id, DoesBits code) { + assert(id < MAX_PLAYERS); + + if(code.up) + moveplayer(id, SPEED); + if(code.down) + moveplayer(id, -SPEED); + if(code.left) + roteplayer(id, -ROTATE); + if(code.right) + roteplayer(id, ROTATE); + if(code.fire) + fireplayer(id); +} + void g_update() { for(int i = 0; i < MAX_PLAYERS; i++) { if(g_player[i].live) { @@ -58,8 +130,46 @@ void g_update() { g_player[i].x += g_player[i].vx; g_player[i].y += g_player[i].vy; g_player[i].r += g_player[i].vr; + + gravity(&g_player[i].vx, &g_player[i].vy, g_player[i].x, g_player[i].y); + checkspacebound(&g_player[i].x); checkspacebound(&g_player[i].y); + + ++g_player[i].shoot; + if(g_player[i].shoot > PLAYER_SHOOT) + g_player[i].shoot = PLAYER_SHOOT; + + if(collide(g_player[i].x, g_player[i].y, PLAYER_SIZE, 0, 0, STAR_SIZE)) + g_player[i].live = false; + } + } + + for(int i = 0; i < MAX_BULLETS; i++) { + if(g_bullet[i].live) { + g_bullet[i].updated = true; + g_bullet[i].tick += 1; + g_bullet[i].x += g_bullet[i].vx; + g_bullet[i].y += g_bullet[i].vy; + + checkspacebound(&g_bullet[i].x); + checkspacebound(&g_bullet[i].y); + + gravity(&g_bullet[i].vx, &g_bullet[i].vy, g_bullet[i].x, g_bullet[i].y); + + for(int j = 0; j < MAX_PLAYERS; j++) + if(g_player[j].live) + if(collide(g_bullet[i].x, g_bullet[i].y, 0.0001, g_player[j].x, g_player[j].y, PLAYER_SIZE)) + if(j != g_bullet[i].owner) + g_player[j].live = false; + + if(g_bullet[i].tick > BULLET_TIME) + g_bullet[i].live = false; } } } + +void g_init(bool server_mode) { + svmode = server_mode; + // TODO memset & co +}