d174ba6fd3370c32a6aa45af1ea0f5cd38db4be7
[gbajam22] / src / level.c
1 #include "util.h"
2 #include "debug.h"
3 #include "level.h"
4 #include "player.h"
5
6 struct level *init_level(const char *descstr)
7 {
8         const char *str, *line;
9         int i, j, ncols = 0, nrows = 0;
10         struct level *lvl;
11         struct cell *cell;
12
13         str = line = descstr;
14
15         while(*str) {
16                 if(*str == '\n') {
17                         if(ncols > 0 && str > line && str - line != ncols) {
18                                 panic(get_pc(), "init_level: inconsistent ncols (%d != %d)\n", str - line, ncols);
19                         }
20                         ncols = str - line;
21                         nrows++;
22                         while(*++str == '\n');
23                         line = str;
24                 } else {
25                         str++;
26                 }
27         }
28
29         if(!ispow2(ncols)) {
30                 panic(get_pc(), "init_level: width is not pow2 (%d)\n", ncols);
31         }
32
33         lvl = malloc_nf(sizeof *lvl);
34         lvl->width = ncols;
35         lvl->xmask = ncols - 1;
36         lvl->height = nrows;
37         lvl->orgx = lvl->width >> 1;
38         lvl->orgy = lvl->height >> 1;
39         lvl->cells = calloc_nf(ncols * nrows, sizeof *lvl->cells);
40         lvl->mobs = 0;
41         lvl->items = 0;
42
43         str = descstr;
44         cell = lvl->cells;
45
46         for(i=0; i<nrows; i++) {
47                 for(j=0; j<ncols; j++) {
48                         cell->x = j;
49                         cell->y = i;
50                         if(*str == '#') {
51                                 cell->type = CELL_SOLID;
52                         } else {
53                                 cell->type = CELL_WALK;
54                         }
55                         cell++;
56                         while(*++str == '\n') str++;
57                 }
58         }
59
60         return lvl;
61 }
62
63 void free_level(struct level *lvl)
64 {
65         void *tmp;
66
67         free(lvl->cells);
68
69         while(lvl->mobs) {
70                 tmp = lvl->mobs;
71                 lvl->mobs = lvl->mobs->next;
72                 free(tmp);
73         }
74         while(lvl->items) {
75                 tmp = lvl->items;
76                 lvl->items = lvl->items->next;
77                 free(tmp);
78         }
79 }
80
81 struct {int dx, dy;} visoffs[8][32] = {
82         /* dir 0 */
83         {{-2,-4}, {2,-4}, {-1,-4}, {1,-4}, {0,-4}, {-1,-3}, {1,-3}, {0,-3}, {-1,-2},
84          {1,-2}, {0,-2}, {0,-1}, {0,0}},
85         /* dir 1 */
86         {{4,-4}, {3,-4}, {4,-3}, {2,-4}, {4,-2}, {3,-3}, {2,-3}, {3,-2}, {1,-3},
87          {3,-1}, {2,-2}, {1,-2}, {2,-1}, {1,-1}, {0,0}},
88         /* dir 2 */
89         {{4,-2}, {4,2}, {4,-1}, {4,1}, {4,0}, {3,-1}, {3,1}, {3,0}, {2,-1}, {2,1},
90          {2,0}, {1,0}, {0,0}},
91         /* dir 3 */
92         {{4,4}, {4,3}, {3,4}, {4,2}, {2,4}, {3,3}, {3,2}, {2,3}, {3,1}, {1,3},
93          {2,2}, {2,1}, {1,2}, {1,1}, {0,0}},
94         /* dir 4 */
95         {{-2,4}, {2,4}, {-1,4}, {1,4}, {0,4}, {-1,3}, {1,3}, {0,3}, {-1,2}, {1,2},
96          {0,2}, {0,1}, {0,0}},
97         /* dir 5 */
98         {{-4,4}, {-4,3}, {-3,4}, {-4,2}, {-2,4}, {-3,3}, {-3,2}, {-2,3}, {-3,1},
99          {-1,3}, {-2,2}, {-2,1}, {-1,2}, {-1,1}, {0,0}},
100         /* dir 6 */
101         {{-4,-2}, {-4,2}, {-4,-1}, {-4,1}, {-4,0}, {-3,-1}, {-3,1}, {-3,0}, {-2,-1},
102          {-2,1}, {-2,0}, {-1,0}, {0,0}},
103         /* dir 7 */
104         {{-4,-4}, {-3,-4}, {-4,-3}, {-2,-4}, {-4,-2}, {-3,-3}, {-2,-3}, {-3,-2},
105          {-1,-3}, {-3,-1}, {-2,-2}, {-1,-2}, {-2,-1}, {-1,-1}, {0,0}}
106 };
107
108 void upd_vis(struct level *lvl, struct player *p)
109 {
110         int dir, idx;
111         int x, y;
112         struct cell *cptr;
113
114         pos_to_cell(lvl, p->x, p->y, &p->cx, &p->cy);
115
116         lvl->numvis = 0;
117         idx = -1;
118         dir = 0;        /* TODO use p->theta */
119         do {
120                 idx++;
121                 x = p->cx + visoffs[dir][idx].dx;
122                 y = p->cy + visoffs[dir][idx].dy;
123                 cptr = lvl->cells + y * lvl->width + x;
124                 lvl->vis[lvl->numvis++] = cptr;
125         } while(visoffs[dir][idx].dx | visoffs[dir][idx].dy);
126 }
127
128 void cell_to_pos(struct level *lvl, int cx, int cy, int32_t *px, int32_t *py)
129 {
130         *px = (cx - lvl->orgx) * CELL_SIZE;
131         *py = (cy - lvl->orgy) * CELL_SIZE;
132 }
133
134 void pos_to_cell(struct level *lvl, int32_t px, int32_t py, int *cx, int *cy)
135 {
136         *cx = (px + (CELL_SIZE >> 1)) / CELL_SIZE + lvl->orgx;
137         *cy = (py + (CELL_SIZE >> 1)) / CELL_SIZE + lvl->orgy;
138 }