From 4148d3ff0c0c4b52b0741c38a867a1502600a65f Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Fri, 31 Mar 2017 01:06:51 +0300 Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?utf8?q?=D0=B0=20=D1=81=D1=82=D1=80=D0=B5=D0=BB=D1=8C=D0=B1=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- client.c | 14 ++++++++ game.c | 95 +++++++++++++++++++++++++++++++++++++++++++++--------- game.h | 20 ++++++++++-- netwar.c | 17 ++++++++-- protocol.h | 29 ++++++++++++++++- server.c | 19 +++++++++-- 6 files changed, 171 insertions(+), 23 deletions(-) diff --git a/client.c b/client.c index defe5ec..c1c9a55 100644 --- a/client.c +++ b/client.c @@ -38,6 +38,19 @@ static void cl_update_svplayer(ProtocolMessage m) { ); } +static void cl_update_svbullet(ProtocolMessage m) { + g_bullet_set( + m.sv.sbul.id, + m.sv.sbul.owner, + m.sv.sbul.live, + b2f(m.sv.sbul.x), + b2f(m.sv.sbul.y), + b2f(m.sv.sbul.vx), + b2f(m.sv.sbul.vy), + m.sv.sbul.tick + ); +} + void cl_connect(const char * host, uint16_t port) { if(SDLNet_ResolveHost(&addr, host, (port) ? (port) : (DEFAULT_PORT)) != 0) { SDL_Log("Unable to resolve host: %s\n", SDLNet_GetError()); @@ -80,6 +93,7 @@ void cl_recv() { case SV_INFO: cl_update_svinfo(m); break; case SV_KILL: cl_kill_client(m); break; case SV_SPLR: cl_update_svplayer(m); break; + case SV_SBUL: cl_update_svbullet(m); break; default: SDL_Log("invalid message %i", m.type); } } diff --git a/game.c b/game.c index cbc8e15..2191418 100644 --- a/game.c +++ b/game.c @@ -8,35 +8,77 @@ #define SPEED 0.00006 #define ROTATE 0.00004 +#define BULL_SPEED 0.008 Player g_player[MAX_PLAYERS]; +Bullet g_bullet[MAX_BULLETS]; + +void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr) { + assert(id < MAX_PLAYERS); + g_player[id] = (Player) { + .updated = true, + .live = live, + .x = x, + .y = y, + .r = r, + .vx = vx, + .vy = vy, + .vr = vr, + }; +} + +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) { 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); } +static void roteplayer(int id, float speed) { + g_player[id].vr += speed; +} + +static void fireplayer(int id) { + int j = freebullet(); + if(j < 0) + return; + + 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 = abs(x); + x = fabs(x); else if(x > 1) x = -x; *a = x; } -void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr) { - assert(id < MAX_PLAYERS); - g_player[id] = (Player) { - .updated = true, - .live = live, - .x = x, - .y = y, - .r = r, - .vx = vx, - .vy = vy, - .vr = vr, - }; +static bool collide(float x1, float y1, float r1, float x2, float y2, float r2) { + float l = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2)); + return ((l - r1 - r2) <= 0); } void g_player_does(unsigned int id, DoesCode code) { @@ -45,9 +87,9 @@ void g_player_does(unsigned int id, DoesCode code) { 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; + case DOES_LEFT: roteplayer(id, -ROTATE); break; + case DOES_RIGHT: roteplayer(id, ROTATE); break; + case DOES_FIRE: fireplayer(id); break; } } @@ -62,4 +104,25 @@ void g_update() { checkspacebound(&g_player[i].y); } } + + 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); + + 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; + } + } } diff --git a/game.h b/game.h index 17c2b68..7bf9d1e 100644 --- a/game.h +++ b/game.h @@ -2,8 +2,10 @@ #include "protocol.h" -#define MAX_PLAYERS 64 -#define TICK_DELAY (1000 / 60) +#define MAX_PLAYERS 32 +#define MAX_BULLETS (MAX_PLAYERS * 8) +#define TICK_DELAY (1000 / 30) +#define BULLET_TIME (TICK_DELAY * 6) #define PLAYER_SIZE 0.01785 typedef struct Player { @@ -16,8 +18,22 @@ typedef struct Player { bool updated; } Player; +typedef struct Bullet { + /* public */ + bool live; + int owner; + float x, y; + float vx, vy; + int tick; + + /* internal */ + bool updated; +} Bullet; + extern Player g_player[MAX_PLAYERS]; +extern Bullet g_bullet[MAX_BULLETS]; void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr); +void g_bullet_set(unsigned int id, unsigned int owner, bool live, float x, float y, float vx, float vy, int tick); void g_player_does(unsigned int id, DoesCode code); void g_update(); diff --git a/netwar.c b/netwar.c index 2419456..b18f8ac 100644 --- a/netwar.c +++ b/netwar.c @@ -110,6 +110,19 @@ static void paintwindow() { SDL_RenderDrawLines(renderer, pixship, count); } + for(int i = 0; i < MAX_BULLETS; i++) { + if(g_bullet[i].owner == cl_playerid) + SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00); + else + SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0x00); + + int x = g_bullet[i].x * WIDTH / 2; + int y = g_bullet[i].y * HEIGHT / 2; + + if(g_bullet[i].live) + SDL_RenderDrawPoint(renderer, cx + x, cy + y); + } + SDL_RenderPresent(renderer); } @@ -144,6 +157,8 @@ int main(int argc, char ** argv) { if(event.type == SDL_QUIT) goto cleanup; + cl_recv(); + if(currTime - lastTime >= TICK_DELAY) { keyboardhandle(); g_update(); @@ -151,8 +166,6 @@ int main(int argc, char ** argv) { } currTime = SDL_GetTicks(); - cl_recv(); - paintwindow(); SDL_Delay(1); diff --git a/protocol.h b/protocol.h index 2681553..a20c773 100644 --- a/protocol.h +++ b/protocol.h @@ -6,7 +6,7 @@ #include #define DEFAULT_PORT 29386 -#define PROTOCOL_VERSION 0 +#define PROTOCOL_VERSION 1 #define PROTOCOL_F8FRAC (1 << 7) #define PACKED __attribute__((__packed__)) @@ -21,6 +21,7 @@ typedef enum { SV_INFO = 128, SV_KILL = 139, SV_SPLR = 130, + SV_SBUL = 131, } MessageType; typedef enum { @@ -67,6 +68,16 @@ typedef struct PACKED SvSplr { uint8_t vx, vy, vr; } SvSplr; +typedef struct PACKED SvSbul { + uint8_t type; + uint8_t id; + uint8_t owner; + uint8_t live; + uint8_t x, y; + uint8_t vx, vy; + uint8_t tick; +} SvSbul; + typedef union ClMessage { uint8_t type; ClInfo info; @@ -79,6 +90,7 @@ typedef union SvMessage { SvInfo info; SvKill kill; SvSplr splr; + SvSbul sbul; } SvMessage; typedef union ProtocolMessage { @@ -99,6 +111,7 @@ static inline int MessageTypeSize(MessageType type) { case SV_INFO: return sizeof(SvInfo); case SV_KILL: return sizeof(SvKill); case SV_SPLR: return sizeof(SvSplr); + case SV_SBUL: return sizeof(SvSbul); default: return sizeof(ProtocolMessage); } } @@ -162,6 +175,20 @@ static inline ProtocolMessage sv_splr(int clid, bool live, float x, float y, flo }; } +static inline ProtocolMessage sv_sbul(int id, int owner, bool live, float x, float y, float vx, float vy, int tick) { + return (ProtocolMessage) (SvMessage) (SvSbul) { + .type = SV_SBUL, + .id = id, + .owner = owner, + .live = live, + .x = f2b(x), + .y = f2b(y), + .vx = f2b(vx), + .vy = f2b(vy), + .tick = tick, + }; +} + #undef PACKED #endif /* PROTOCOL_H_INCLUDED */ diff --git a/server.c b/server.c index ea28583..d6cbfcc 100644 --- a/server.c +++ b/server.c @@ -48,6 +48,15 @@ static void sv_sync_client(int id, bool full) { for(int i = 0; i < clientlimit; i++) if(full || g_player[i].updated) SendMessage(sock, client[id].address, sv_splr(i, g_player[i].live, g_player[i].x, g_player[i].y, g_player[i].r, g_player[i].vx, g_player[i].vy, g_player[i].vr)); + + for(int i = 0; i < MAX_BULLETS; i++) + if(full || g_bullet[i].updated) + SendMessage(sock, client[id].address, sv_sbul(i, g_bullet[i].owner, g_bullet[i].live, g_bullet[i].x, g_bullet[i].y, g_bullet[i].vx, g_bullet[i].vy, g_bullet[i].tick)); +} + +static void sv_spawn_player(int id) { + assert(id >= 0); + g_player_set(id, true, randfm(), randfm(), randfm(), 0, 0, 0); } static void sv_kill_player(int id, bool send, const char * msg) { @@ -66,6 +75,9 @@ static void sv_move_player(int id, ProtocolMessage m) { assert(id >= 0); assert(client[id].connected); + if(!g_player[id].live) + sv_spawn_player(id); + g_player_does(id, m.cl.does.code); } @@ -92,7 +104,7 @@ static void sv_register_player(IPaddress address, ProtocolMessage m) { SDL_Log("Player %s (%i) connected", client[i].name, i); SendMessage(sock, address, sv_info(name, i, clientlimit)); - g_player_set(i, true, randfm(), randfm(), randfm(), 0, 0, 0); + sv_spawn_player(i); sv_sync_client(i, true); } @@ -114,9 +126,12 @@ static void sv_send() { for(int i = 0; i < clientlimit; i++) if(client[i].connected) sv_sync_client(i, false); - + for(int i = 0; i < clientlimit; i++) g_player[i].updated = false; + + for(int i = 0; i < MAX_BULLETS; i++) + g_bullet[i].updated = false; } void sv_start(uint16_t port) { -- 2.29.2