3 static const int step[][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
5 void init_player(struct player *p)
7 memset(p, 0, sizeof *p);
8 cgm_qcons(&p->vrot, 0, 0, 0, 1);
11 p->hp = p->hp_max = 10;
12 p->mp = p->mp_max = 10;
15 #define TWO_PI ((float)M_PI * 2.0f)
16 #define HALF_PI ((float)M_PI / 2.0f)
18 void update_player_dir(struct player *p)
20 int prev_dir = p->dir;
23 /* TODO: take vrot into account */
24 angle = fmod(p->theta, TWO_PI);
25 if(angle < 0) angle += TWO_PI;
27 p->theta = angle; /* renormalize theta */
28 p->dir = (int)(4.0f * angle / TWO_PI + 0.5) & 3;
30 if(p->dir != prev_dir) {
31 p->vis = 0; /* invalidate visibility list */
35 void move_player(struct player *p, int right, int fwd)
42 rdir = (fdir + 1) & 3;
43 p->cx += step[fdir][0] * fwd + step[rdir][0] * right;
44 p->cy += step[fdir][1] * fwd + step[rdir][1] * right;
46 p->vis = 0; /* invalidate visibility list */
49 void turn_player(struct player *p, int turn)
53 p->theta += turn > 0 ? HALF_PI : -HALF_PI;
56 p->theta = (float)p->dir * HALF_PI; /* snap theta */
58 p->vis = 0; /* invalidate visibility list */
61 void upd_player_xform(struct player *p)
64 float celld = p->lvl ? p->lvl->cell_size : DEF_CELL_SIZE;
66 cgm_vcons(&pos, p->cx * celld, p->height, -p->cy * celld);
67 cgm_vadd(&pos, &p->cpos);
69 cgm_midentity(p->view_xform);
70 cgm_mprerotate_x(p->view_xform, -p->phi);
71 cgm_mprerotate_y(p->view_xform, p->theta);
72 cgm_mrotate_quat(p->view_xform, &p->vrot);
73 cgm_mpretranslate(p->view_xform, -pos.x, -pos.y, -pos.z);
76 static void vis_visit(struct player *p, int cx, int cy, int *cvis)
78 int i, j, nx, ny, dx, dy;
79 struct level *lvl = p->lvl;
82 if(cx < 0 || cx >= lvl->width || cy < 0 || cy >= lvl->height) {
85 cell = lvl->cells + cy * lvl->width + cx;
87 /* stop when we encounter a solid cell */
88 if(cell->type == CELL_SOLID) {
94 /* stop beyond the maximum visibility distance (manhattan) */
95 if(abs(dx) > lvl->visdist || abs(dy) > lvl->visdist) {
100 if(step[p->dir][0] * dx + step[p->dir][1] * dy < 0) {
101 return; /* cell is behind the player */
104 cvis[cy * lvl->width + cx] = 1; /* mark as visited before recursing */
106 /* visit neighboring nodes before adding current cell */
110 if(ny >= lvl->height) break;
113 if(i == 1 && j == 1) continue;
116 if(nx >= lvl->width) break;
118 if(!cvis[ny * lvl->width + nx]) {
119 vis_visit(p, nx, ny, cvis);
124 /* then add this cell to the visible list */
129 void upd_player_vis(struct player *p)
132 struct level *lvl = p->lvl;
134 cvis = alloca(lvl->width * lvl->height * sizeof *cvis);
135 memset(cvis, 0, lvl->width * lvl->height * sizeof *cvis);
138 vis_visit(p, p->cx, p->cy, cvis);