-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayers.c
173 lines (133 loc) · 5.02 KB
/
players.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <stdlib.h>
#include <bitbox.h>
#include "players.h"
#include "terrain.h"
#include "char1.h"
Player player[2];
#define min(a,b) ((a)<(b) ? (a) : (b))
void players_init()
{
for (int i=0; i<2; i++)
{
Player *p = &player[i];
p->sprite_width = _char1_tw;
p->sprite_height = _char1_th;
p->data = _char1_data;
p->col = 1 +i*(MWIDTH-3);
p->row = 1 +i*(MHEIGHT-3);
p->rem_bombs = 1;
p->bomb_range = 0;
p->life = 3;
p->speed = 3;
}
}
/*
* Update player position and directions according to gamepad button pressed
* The direction is updated as soon as the button is pressed, however the movement
* of the sprite follow the grid, hence the multiple states in the direction.
*/
void players_update()
{
for(int pi=0; pi<2; pi++)
{
uint16_t buttons = gamepad_buttons[pi];
Player *p = &player[pi];
int i = p->col;
int j = p->row;
// Update timed ressources
if (p->shield)
p->shield--;
// Are we still alive BTW ?
if (terrain_ovr[j][i] >= MT_EXPL0 && terrain_ovr[j][i] <= MT_EXPL4 && p->shield == 0)
{
// We got fire !
if (!p->life)
{
// TODO handle death here....
message("really dead this time\n");
break;
}
p->life--;
p->shield = 120; // seconds shield
break;
}
char btndir = ( buttons >> 8) & 0xF;
// Make sure we only have one bit set in the direction button bitfield
int c;
for(c=1; c<=8; c<<=1)
if (btndir&c) break;
btndir = c & 0xF;
// Update player position if there is a button pressed
if (btndir)
{
// Compute forward-backward pos depending on btndir direction
int fbpos = (btndir&DIR_HORZ) ? p->xoff : p->yoff;
fbpos = (btndir&DIR_RD) ? fbpos : -fbpos ;
int step = p->speed;
// If we are approaching the next block (in forward direction) ( => check colision with non walk-able blocks)
if (fbpos <= 2 && fbpos+step>2)
{
// Increments to compute surounding cases:
// * forward: +a, +b
// * backward: -a, -b
// * left: +b, -a
// * right: -b, +a
int a = ((btndir>>3)&1) - ((btndir>>2)&1);
int b = ((btndir>>1)&1) - (btndir&1);
// Compute right-left pos depending on btndir direction
int rlpos = (btndir&DIR_HORZ) ? p->yoff : p->xoff;
rlpos = (btndir&DIR_UR) ? rlpos : -rlpos ;
char orthaxe = (btndir&DIR_HORZ) ? DIR_VERT : DIR_HORZ; // orthogonal axe to btndir
char leftdir = (btndir&DIR_UR) ? orthaxe&DIR_LU : orthaxe&DIR_RD;
// Check if block in btndir direction is walk-able
if (!terrain_canwalk(i+a, j+b))
{
step = 2 - fbpos;
if (!step)
btndir = 0;
}
else
{
// If the forward left block is non walk-able, need to align on the horiz grid
if (rlpos < -2 && !terrain_canwalk(i+a+b, j+b-a))
{
btndir = leftdir^orthaxe;
step = min(step, -2-rlpos);
}
// If the forward left block is non walk-able, need to align on the horiz grid
else if (rlpos > 2 && !terrain_canwalk(i+a-b, j+b+a))
{
btndir = leftdir;
step = min(step, rlpos-2);
}
}
}
// Move the player sprite according to direction
p->xoff += (((btndir>>3)&1) - ((btndir>>2)&1)) * step;
p->yoff += ((((btndir>>1)&1) - (btndir&1))) * step;
// Change postion on the grid
if (p->xoff > 16 || p->xoff <= -16)
{
p->col += ((btndir>>3)&1) - ((btndir>>2)&1);
p->xoff += p->xoff < 0 ? 32 : -32;
}
if (p->yoff > 16 || p->yoff <= -16)
{
p->row += ((btndir>>1)&1) - (btndir&1);
p->yoff += p->yoff < 0 ? 32 : -32;
}
//message("%d %d\n", p->xoff, p->yoff);
}
// Drop bombs !
if (buttons&gamepad_A)
{
if (terrain_canwalk(i, j) && p->rem_bombs)
{
p->rem_bombs--;
terrain_ovr[j][i] = MT_BOMB1;
// 2 seconds timeout for a bomb
terrain_data[j][i] = 60 | (p->bomb_range<<8) | (pi<<12);
}
}
}
}