DEADSOFTWARE

Добавлено ограничение максимального ускорения
[netwar.git] / game.c
1 #include <SDL2/SDL.h>
3 #include <assert.h>
4 #include <stdbool.h>
5 #include <math.h>
7 #include "game.h"
9 #define SPEED (0.03 / TICK)
10 #define ROTATE (0.03 / TICK)
11 #define BULL_SPEED (0.4 / TICK)
13 #define MAX_SPEED (0.3 / TICK)
14 #define MAX_ROTATE (0.3 / TICK)
16 Player g_player[MAX_PLAYERS];
17 Bullet g_bullet[MAX_BULLETS];
19 static bool svmode;
21 void g_player_set(unsigned int id, bool live, float x, float y, float r, float vx, float vy, float vr, int shoot) {
22 assert(id < MAX_PLAYERS);
23 g_player[id] = (Player) {
24 .updated = true,
25 .live = live,
26 .x = x,
27 .y = y,
28 .r = r,
29 .vx = vx,
30 .vy = vy,
31 .vr = vr,
32 };
33 }
35 void g_bullet_set(unsigned int id, unsigned int owner, bool live, float x, float y, float vx, float vy, int tick) {
36 assert(id < MAX_BULLETS);
37 assert(owner < MAX_PLAYERS);
38 g_bullet[id] = (Bullet) {
39 .live = live,
40 .owner = owner,
41 .x = x,
42 .y = y,
43 .vx = vx,
44 .vy = vy,
45 .tick = tick,
46 };
47 }
49 static int freebullet() {
50 for(int i = 0; i < MAX_BULLETS; i++)
51 if(!g_bullet[i].live)
52 return i;
53 return -1;
54 }
56 static void moveplayer(int id, float speed) {
57 g_player[id].vx += speed * cos(g_player[id].r * 2 * M_PI);
58 g_player[id].vy += speed * sin(g_player[id].r * 2 * M_PI);
60 if(fabs(g_player[id].vx) > MAX_SPEED)
61 g_player[id].vx = copysignf(MAX_SPEED, g_player[id].vx);
62 if(fabs(g_player[id].vy) > MAX_SPEED)
63 g_player[id].vy = copysignf(MAX_SPEED, g_player[id].vy);
64 }
66 static void roteplayer(int id, float speed) {
67 g_player[id].vr += speed;
68 if(fabs(g_player[id].vr) > MAX_ROTATE)
69 g_player[id].vr = copysignf(MAX_ROTATE, g_player[id].vr);
70 }
72 static void fireplayer(int id) {
73 int j = freebullet();
74 if(j < 0)
75 return;
77 if(g_player[id].shoot < PLAYER_SHOOT)
78 return;
80 g_player[id].shoot = 0;
82 if(svmode) {
83 float vx = BULL_SPEED * cos(g_player[id].r * 2 * M_PI);
84 float vy = BULL_SPEED * sin(g_player[id].r * 2 * M_PI);
85 g_bullet_set(j, id, true, g_player[id].x, g_player[id].y, vx, vy, 0);
86 }
87 }
89 static void checkspacebound(float * a) {
90 float x = *a;
91 if(x < -1)
92 x = fabs(x);
93 else if(x > 1)
94 x = -x;
95 *a = x;
96 }
98 static bool collide(float x1, float y1, float r1, float x2, float y2, float r2) {
99 float l = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
100 return ((l - r1 - r2) <= 0);
103 void g_player_does(unsigned int id, DoesBits code) {
104 assert(id < MAX_PLAYERS);
106 if(code.up)
107 moveplayer(id, SPEED);
108 if(code.down)
109 moveplayer(id, -SPEED);
110 if(code.left)
111 roteplayer(id, -ROTATE);
112 if(code.right)
113 roteplayer(id, ROTATE);
114 if(code.fire)
115 fireplayer(id);
118 void g_update() {
119 for(int i = 0; i < MAX_PLAYERS; i++) {
120 if(g_player[i].live) {
121 g_player[i].updated = true;
122 g_player[i].x += g_player[i].vx;
123 g_player[i].y += g_player[i].vy;
124 g_player[i].r += g_player[i].vr;
125 checkspacebound(&g_player[i].x);
126 checkspacebound(&g_player[i].y);
128 ++g_player[i].shoot;
129 if(g_player[i].shoot > PLAYER_SHOOT)
130 g_player[i].shoot = PLAYER_SHOOT;
134 for(int i = 0; i < MAX_BULLETS; i++) {
135 if(g_bullet[i].live) {
136 g_bullet[i].updated = true;
137 g_bullet[i].tick += 1;
138 g_bullet[i].x += g_bullet[i].vx;
139 g_bullet[i].y += g_bullet[i].vy;
141 checkspacebound(&g_bullet[i].x);
142 checkspacebound(&g_bullet[i].y);
144 for(int j = 0; j < MAX_PLAYERS; j++)
145 if(g_player[j].live)
146 if(collide(g_bullet[i].x, g_bullet[i].y, 0.0001, g_player[j].x, g_player[j].y, PLAYER_SIZE))
147 if(j != g_bullet[i].owner)
148 g_player[j].live = false;
150 if(g_bullet[i].tick > BULLET_TIME)
151 g_bullet[i].live = false;
156 void g_init(bool server_mode) {
157 svmode = server_mode;
158 // TODO memset & co