summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c4b04d1)
raw | patch | inline | side by side (parent: c4b04d1)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Thu, 30 Mar 2017 22:06:51 +0000 (01:06 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Thu, 30 Mar 2017 22:06:51 +0000 (01:06 +0300) |
client.c | patch | blob | history | |
game.c | patch | blob | history | |
game.h | patch | blob | history | |
netwar.c | patch | blob | history | |
protocol.h | patch | blob | history | |
server.c | patch | blob | history |
diff --git a/client.c b/client.c
index defe5ec757891aad33ee0c4d92dc8d3338163b1d..c1c9a557c7368229b647ebea1467f47c2d6c0207 100644 (file)
--- a/client.c
+++ b/client.c
);
}
+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());
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);
}
}
index cbc8e156ce5ff24ec6ef70e1a9150f34052f8a3d..219141884dd23ba9a59b2643135c78fcd83568e5 100644 (file)
--- a/game.c
+++ b/game.c
#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) {
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;
}
}
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;
+ }
+ }
}
index 17c2b68dfafec9a26463c9db8624a2fd732069c9..7bf9d1e5621aa8838cb760bb39e4e0df0e54820e 100644 (file)
--- a/game.h
+++ b/game.h
#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 {
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 2419456d87d0dea2265c5f9e47422286359258ab..b18f8ac9d7a5f288d546dcacbd8de65f30a3629e 100644 (file)
--- a/netwar.c
+++ b/netwar.c
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);
}
if(event.type == SDL_QUIT)
goto cleanup;
+ cl_recv();
+
if(currTime - lastTime >= TICK_DELAY) {
keyboardhandle();
g_update();
}
currTime = SDL_GetTicks();
- cl_recv();
-
paintwindow();
SDL_Delay(1);
diff --git a/protocol.h b/protocol.h
index 26815532050839457926e8bb89b51c21bd170a71..a20c773d16fbe0751ac5fcb6b6f9da3c4f05b233 100644 (file)
--- a/protocol.h
+++ b/protocol.h
#include <string.h>
#define DEFAULT_PORT 29386
-#define PROTOCOL_VERSION 0
+#define PROTOCOL_VERSION 1
#define PROTOCOL_F8FRAC (1 << 7)
#define PACKED __attribute__((__packed__))
SV_INFO = 128,
SV_KILL = 139,
SV_SPLR = 130,
+ SV_SBUL = 131,
} MessageType;
typedef enum {
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;
SvInfo info;
SvKill kill;
SvSplr splr;
+ SvSbul sbul;
} SvMessage;
typedef union ProtocolMessage {
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 ea28583e06de04a2ead618e666593f6e92e2dc22..d6cbfcc3b3c07cb1670bb914466dd414dca5136d 100644 (file)
--- a/server.c
+++ b/server.c
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) {
assert(id >= 0);
assert(client[id].connected);
+ if(!g_player[id].live)
+ sv_spawn_player(id);
+
g_player_does(id, m.cl.does.code);
}
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);
}
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) {