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 // Цифры взяты с потолка, но вроде неплохо подобраны
21 Player g_player
[MAX_PLAYERS
];
22 Bullet g_bullet
[MAX_BULLETS
];
26 void g_player_set(unsigned int id
, bool live
, float x
, float y
, float r
, float vx
, float vy
, float vr
, int shoot
) {
27 assert(id
< MAX_PLAYERS
);
28 g_player
[id
] = (Player
) {
40 void g_bullet_set(unsigned int id
, unsigned int owner
, bool live
, float x
, float y
, float vx
, float vy
, int tick
) {
41 assert(id
< MAX_BULLETS
);
42 assert(owner
< MAX_PLAYERS
);
43 g_bullet
[id
] = (Bullet
) {
54 static int freebullet() {
55 for(int i
= 0; i
< MAX_BULLETS
; i
++)
61 static void moveplayer(int id
, float speed
) {
62 g_player
[id
].vx
+= speed
* cos(g_player
[id
].r
* 2 * M_PI
);
63 g_player
[id
].vy
+= speed
* sin(g_player
[id
].r
* 2 * M_PI
);
65 if(fabs(g_player
[id
].vx
) > MAX_SPEED
)
66 g_player
[id
].vx
= copysignf(MAX_SPEED
, g_player
[id
].vx
);
67 if(fabs(g_player
[id
].vy
) > MAX_SPEED
)
68 g_player
[id
].vy
= copysignf(MAX_SPEED
, g_player
[id
].vy
);
71 static void roteplayer(int id
, float speed
) {
72 g_player
[id
].vr
+= speed
;
73 if(fabs(g_player
[id
].vr
) > MAX_ROTATE
)
74 g_player
[id
].vr
= copysignf(MAX_ROTATE
, g_player
[id
].vr
);
77 static void fireplayer(int id
) {
82 if(g_player
[id
].shoot
< PLAYER_SHOOT
)
85 g_player
[id
].shoot
= 0;
88 float vx
= BULL_SPEED
* cos(g_player
[id
].r
* 2 * M_PI
);
89 float vy
= BULL_SPEED
* sin(g_player
[id
].r
* 2 * M_PI
);
90 g_bullet_set(j
, id
, true, g_player
[id
].x
, g_player
[id
].y
, vx
, vy
, 0);
94 static void checkspacebound(float * a
) {
103 static float length(float x1
, float y1
, float x2
, float y2
) {
104 return sqrtf(powf(x1
- x2
, 2) + powf(y1
- y2
, 2));
107 static bool collide(float x1
, float y1
, float r1
, float x2
, float y2
, float r2
) {
108 return ((length(x1
, y1
, x2
, y2
) - r1
- r2
) <= 0);
111 static void gravity(float * vx
, float * vy
, float x
, float y
) {
112 *vx
+= copysign(G
* M_STAR
* M_SHIP
/ length(0, 0, x
, y
), x
* -1);
113 *vy
+= copysign(G
* M_STAR
* M_SHIP
/ length(0, 0, x
, y
), y
* -1);
116 void g_player_does(unsigned int id
, DoesBits code
) {
117 assert(id
< MAX_PLAYERS
);
120 moveplayer(id
, SPEED
);
122 moveplayer(id
, -SPEED
);
124 roteplayer(id
, -ROTATE
);
126 roteplayer(id
, ROTATE
);
132 for(int i
= 0; i
< MAX_PLAYERS
; i
++) {
133 if(g_player
[i
].live
) {
134 g_player
[i
].updated
= true;
135 g_player
[i
].x
+= g_player
[i
].vx
;
136 g_player
[i
].y
+= g_player
[i
].vy
;
137 g_player
[i
].r
+= g_player
[i
].vr
;
139 gravity(&g_player
[i
].vx
, &g_player
[i
].vy
, g_player
[i
].x
, g_player
[i
].y
);
141 checkspacebound(&g_player
[i
].x
);
142 checkspacebound(&g_player
[i
].y
);
145 if(g_player
[i
].shoot
> PLAYER_SHOOT
)
146 g_player
[i
].shoot
= PLAYER_SHOOT
;
148 if(collide(g_player
[i
].x
, g_player
[i
].y
, PLAYER_SIZE
, 0, 0, STAR_SIZE
))
149 g_player
[i
].live
= false;
153 for(int i
= 0; i
< MAX_BULLETS
; i
++) {
154 if(g_bullet
[i
].live
) {
155 g_bullet
[i
].updated
= true;
156 g_bullet
[i
].tick
+= 1;
157 g_bullet
[i
].x
+= g_bullet
[i
].vx
;
158 g_bullet
[i
].y
+= g_bullet
[i
].vy
;
160 checkspacebound(&g_bullet
[i
].x
);
161 checkspacebound(&g_bullet
[i
].y
);
163 for(int j
= 0; j
< MAX_PLAYERS
; j
++)
165 if(collide(g_bullet
[i
].x
, g_bullet
[i
].y
, 0.0001, g_player
[j
].x
, g_player
[j
].y
, PLAYER_SIZE
))
166 if(j
!= g_bullet
[i
].owner
)
167 g_player
[j
].live
= false;
169 if(g_bullet
[i
].tick
> BULLET_TIME
)
170 g_bullet
[i
].live
= false;
175 void g_init(bool server_mode
) {
176 svmode
= server_mode
;