Mercurial > MadButterfly
comparison examples/tank/tank_main.c @ 131:6a8588df68af
Tank can change direction and navigate on the mud area
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 17 Sep 2008 01:30:25 +0800 |
parents | 3a4d6179e6a9 |
children | c65b30e2eda9 |
comparison
equal
deleted
inserted
replaced
130:3a4d6179e6a9 | 131:6a8588df68af |
---|---|
1 #include <sys/time.h> | 1 #include <sys/time.h> |
2 #include <string.h> | |
2 #include <mb/mb.h> | 3 #include <mb/mb.h> |
4 #include <mb/tools.h> | |
3 #include "svgs.h" | 5 #include "svgs.h" |
4 | 6 |
5 enum { MUD, ROC, BRI, BSH }; | 7 enum { MUD, ROC, BRI, BSH }; |
6 | 8 |
7 static char map[12][16] = { | 9 static char map[12][16] = { |
29 MUD, BRI, MUD, MUD, MUD, BRI, BRI, MUD}, | 31 MUD, BRI, MUD, MUD, MUD, BRI, BRI, MUD}, |
30 { MUD, MUD, MUD, MUD, MUD, MUD, BRI, MUD, | 32 { MUD, MUD, MUD, MUD, MUD, MUD, BRI, MUD, |
31 MUD, BRI, MUD, BRI, MUD, MUD, MUD, MUD} | 33 MUD, BRI, MUD, BRI, MUD, MUD, MUD, MUD} |
32 }; | 34 }; |
33 | 35 |
36 #define MAP_W 16 | |
37 #define MAP_H 12 | |
38 | |
39 /*! \defgroup tank_elf Tank Elf | |
40 * \brief Tank elf module provides control functions of tanks in game. | |
41 * @{ | |
42 */ | |
43 struct _tank { | |
44 coord_t *coord_pos; /*!< \brief coordinate for position */ | |
45 coord_t *coord_rot; /*!< \brief coordinate for rotation */ | |
46 int map_x, map_y; | |
47 int direction; | |
48 mb_progm_t *progm; | |
49 }; | |
50 typedef struct _tank tank_t; | |
51 enum { TD_UP = 0, TD_RIGHT, TD_DOWN, TD_LEFT }; | |
52 | |
53 static tank_t *tank_new(coord_t *coord_pos, | |
54 coord_t *coord_rot, | |
55 int map_x, int map_y, | |
56 X_MB_runtime_t *mb_rt) { | |
57 tank_t *tank; | |
58 redraw_man_t *rdman; | |
59 | |
60 tank = O_ALLOC(tank_t); | |
61 if(tank == NULL) | |
62 return NULL; | |
63 | |
64 rdman = X_MB_rdman(mb_rt); | |
65 | |
66 tank->coord_pos = coord_pos; | |
67 tank->coord_rot = coord_rot; | |
68 tank->map_x = map_x; | |
69 tank->map_y = map_y; | |
70 tank->direction = TD_UP; | |
71 tank->progm = NULL; | |
72 | |
73 memset(coord_pos->matrix, 0, sizeof(co_aix[6])); | |
74 coord_pos->matrix[0] = 1; | |
75 coord_pos->matrix[2] = map_x * 50; | |
76 coord_pos->matrix[4] = 1; | |
77 coord_pos->matrix[5] = map_y * 50; | |
78 rdman_coord_changed(rdman, coord_pos); | |
79 | |
80 return tank; | |
81 } | |
82 | |
83 static void tank_free(tank_t *tank, X_MB_runtime_t *xmb_rt) { | |
84 mb_tman_t *tman; | |
85 | |
86 if(tank->progm) { | |
87 tman = X_MB_tman(xmb_rt); | |
88 mb_progm_abort(tank->progm, tman); | |
89 } | |
90 free(tank); | |
91 } | |
92 | |
93 /*! \brief Clean program for a tank. | |
94 * | |
95 * It is called when the program is completed. | |
96 */ | |
97 static void clean_tank_progm_handler(event_t *event, void *arg) { | |
98 tank_t *tank = (tank_t *)arg; | |
99 | |
100 mb_progm_free(tank->progm); | |
101 tank->progm = NULL; | |
102 } | |
103 | |
104 #define PI 3.1415926 | |
105 | |
106 static void tank_move(tank_t *tank, int direction, | |
107 X_MB_runtime_t *xmb_rt) { | |
108 redraw_man_t *rdman; | |
109 mb_tman_t *tman; | |
110 ob_factory_t *factory; | |
111 /* for the program */ | |
112 mb_progm_t *progm; | |
113 subject_t *comp_sub; | |
114 mb_word_t *word; | |
115 mb_timeval_t start, playing; | |
116 mb_timeval_t now; | |
117 /* for position */ | |
118 co_aix sh_x, sh_y; | |
119 /* for direction */ | |
120 float ang1, ang2; | |
121 float rot_diff; | |
122 static co_aix shift_xy[][2] = {{0, -50}, {50, 0}, {0, 50}, {-50, 0}}; | |
123 static int map_shift[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; | |
124 static float angles[4] = {0, PI / 2, PI , PI * 3 / 2}; | |
125 static float rotations[7] = {PI / 2, PI , -PI / 2, | |
126 0, PI / 2, PI , -PI / 2}; | |
127 | |
128 if(tank->progm != NULL) | |
129 return; | |
130 | |
131 /* | |
132 * Keep inside the map. | |
133 */ | |
134 if(direction == tank->direction) { | |
135 switch(direction) { | |
136 case TD_UP: | |
137 if(tank->map_y == 0) | |
138 return; | |
139 if(map[tank->map_y - 1][tank->map_x] != MUD) | |
140 return; | |
141 break; | |
142 case TD_RIGHT: | |
143 if(tank->map_x >= (MAP_W - 1)) | |
144 return; | |
145 if(map[tank->map_y][tank->map_x + 1] != MUD) | |
146 return; | |
147 break; | |
148 case TD_DOWN: | |
149 if(tank->map_y >= (MAP_H - 1)) | |
150 return; | |
151 if(map[tank->map_y + 1][tank->map_x] != MUD) | |
152 return; | |
153 break; | |
154 case TD_LEFT: | |
155 if(tank->map_x == 0) | |
156 return; | |
157 if(map[tank->map_y][tank->map_x - 1] != MUD) | |
158 return; | |
159 break; | |
160 } | |
161 } | |
162 | |
163 rdman = X_MB_rdman(xmb_rt); | |
164 tman = X_MB_tman(xmb_rt); | |
165 factory = X_MB_ob_factory(xmb_rt); | |
166 | |
167 progm = mb_progm_new(1, rdman); | |
168 tank->progm = progm; | |
169 | |
170 MB_TIMEVAL_SET(&start, 0, 0); | |
171 MB_TIMEVAL_SET(&playing, 0, 500000); | |
172 word = mb_progm_next_word(progm, &start, &playing); | |
173 | |
174 if(direction == tank->direction) { | |
175 /* Shift/move */ | |
176 sh_x = shift_xy[direction][0]; | |
177 sh_y = shift_xy[direction][1]; | |
178 mb_shift_new(sh_x, sh_y, tank->coord_pos, word); | |
179 tank->map_x += map_shift[direction][0]; | |
180 tank->map_y += map_shift[direction][1]; | |
181 } else { | |
182 /* Change direction */ | |
183 rot_diff = rotations[3 - tank->direction + direction]; | |
184 ang1 = angles[tank->direction]; | |
185 ang2 = ang1 + rot_diff; | |
186 mb_rotate_new(ang1, ang2, tank->coord_rot, word); | |
187 tank->direction = direction; | |
188 } | |
189 | |
190 /* Clean program when it is completed. */ | |
191 comp_sub = mb_progm_get_complete(progm); | |
192 subject_add_observer(factory, comp_sub, | |
193 clean_tank_progm_handler, tank); | |
194 | |
195 get_now(&now); | |
196 mb_progm_start(progm, tman, &now); | |
197 } | |
198 | |
199 /* @} */ | |
200 | |
34 typedef struct _tank_rt tank_rt_t; | 201 typedef struct _tank_rt tank_rt_t; |
35 | 202 |
36 struct _tank_rt { | 203 struct _tank_rt { |
37 tank1_t *tank1; | 204 tank_t *tank1; |
38 tank2_t *tank2; | 205 tank1_t *tank1_o; |
206 tank_t *tank2; | |
207 tank2_t *tank2_o; | |
39 int n_enemy; | 208 int n_enemy; |
40 tank_en_t *tank_enemies[10]; | 209 tank_t *tank_enemies[10]; |
210 tank_en_t *tank_enemies_o[10]; | |
41 void *map[12][16]; | 211 void *map[12][16]; |
42 X_MB_runtime_t *mb_rt; | 212 X_MB_runtime_t *mb_rt; |
43 | |
44 mb_progm_t *tank1_progm; | |
45 | |
46 observer_t *kb_observer; | 213 observer_t *kb_observer; |
47 }; | 214 }; |
48 | 215 |
49 #define CHANGE_POS(g, x, y) do { \ | 216 #define CHANGE_POS(g, x, y) do { \ |
50 (g)->root_coord->matrix[0] = 1.0; \ | 217 (g)->root_coord->matrix[0] = 1.0; \ |
52 (g)->root_coord->matrix[4] = 1.0; \ | 219 (g)->root_coord->matrix[4] = 1.0; \ |
53 (g)->root_coord->matrix[5] = y; \ | 220 (g)->root_coord->matrix[5] = y; \ |
54 rdman_coord_changed(rdman, (g)->root_coord); \ | 221 rdman_coord_changed(rdman, (g)->root_coord); \ |
55 } while(0) | 222 } while(0) |
56 | 223 |
57 static void free_progm_handler(event_t *event, void *arg) { | |
58 tank_rt_t *tank_rt = (tank_rt_t *)arg; | |
59 | |
60 mb_progm_free(tank_rt->tank1_progm); | |
61 tank_rt->tank1_progm = NULL; | |
62 } | |
63 | |
64 static void keyboard_handler(event_t *event, void *arg) { | 224 static void keyboard_handler(event_t *event, void *arg) { |
65 X_kb_event_t *xkey = (X_kb_event_t *)event; | 225 X_kb_event_t *xkey = (X_kb_event_t *)event; |
66 tank_rt_t *tank_rt = (tank_rt_t *)arg; | 226 tank_rt_t *tank_rt = (tank_rt_t *)arg; |
67 redraw_man_t *rdman; | 227 int direction; |
68 mb_tman_t *tman; | 228 |
69 mb_word_t *word; | 229 if(xkey->event.type != EVT_KB_PRESS) |
70 ob_factory_t *factory; | |
71 subject_t *comp_sub; | |
72 mb_timeval_t start_tm, playing, now; | |
73 | |
74 if(tank_rt->tank1_progm != NULL) | |
75 return; | 230 return; |
76 | |
77 rdman = X_MB_rdman(tank_rt->mb_rt); | |
78 tman = X_MB_tman(tank_rt->mb_rt); | |
79 | |
80 tank_rt->tank1_progm = mb_progm_new(2, rdman); | |
81 comp_sub = mb_progm_get_complete(tank_rt->tank1_progm); | |
82 factory = rdman_get_ob_factory(rdman); | |
83 subject_add_observer(factory, comp_sub, | |
84 free_progm_handler, | |
85 tank_rt); | |
86 | |
87 MB_TIMEVAL_SET(&start_tm, 0, 0); | |
88 MB_TIMEVAL_SET(&playing, 0, 500000); | |
89 word = mb_progm_next_word(tank_rt->tank1_progm, | |
90 &start_tm, &playing); | |
91 | 231 |
92 switch(xkey->sym) { | 232 switch(xkey->sym) { |
93 case 0xff51: /* left */ | 233 case 0xff51: /* left */ |
94 mb_shift_new(-50, 0, tank_rt->tank1->root_coord, word); | 234 direction = TD_LEFT; |
95 break; | 235 break; |
96 | 236 |
97 case 0xff52: /* up */ | 237 case 0xff52: /* up */ |
98 mb_shift_new(0, -50, tank_rt->tank1->root_coord, word); | 238 direction = TD_UP; |
99 break; | 239 break; |
100 | 240 |
101 case 0xff53: /* right */ | 241 case 0xff53: /* right */ |
102 mb_shift_new(50, 0, tank_rt->tank1->root_coord, word); | 242 direction = TD_RIGHT; |
103 break; | 243 break; |
104 | 244 |
105 case 0xff54: /* down */ | 245 case 0xff54: /* down */ |
106 mb_shift_new(0, 50, tank_rt->tank1->root_coord, word); | 246 direction = TD_DOWN; |
107 break; | 247 break; |
108 | 248 |
109 case 0x20: /* space */ | 249 case 0x20: /* space */ |
110 case 0xff0d: /* enter */ | 250 case 0xff0d: /* enter */ |
111 break; | 251 default: |
112 } | 252 return; |
113 get_now(&now); | 253 } |
114 mb_progm_start(tank_rt->tank1_progm, tman, &now); | 254 |
255 tank_move(tank_rt->tank1, direction, tank_rt->mb_rt); | |
115 } | 256 } |
116 | 257 |
117 static void init_keyboard(tank_rt_t *tank_rt) { | 258 static void init_keyboard(tank_rt_t *tank_rt) { |
118 X_MB_runtime_t *mb_rt; | 259 X_MB_runtime_t *mb_rt; |
119 subject_t *kbevents; | 260 subject_t *kbevents; |
128 | 269 |
129 tank_rt->kb_observer = | 270 tank_rt->kb_observer = |
130 subject_add_observer(factory, kbevents, keyboard_handler, tank_rt); | 271 subject_add_observer(factory, kbevents, keyboard_handler, tank_rt); |
131 } | 272 } |
132 | 273 |
274 /*! \brief Make coord objects for elfs (tanks). */ | |
275 static void make_elf_coords(redraw_man_t *rdman, coord_t **coord_pos, | |
276 coord_t **coord_rot, coord_t **coord_center) { | |
277 coord_t *coord_back; | |
278 | |
279 *coord_pos = rdman_coord_new(rdman, rdman->root_coord); | |
280 | |
281 coord_back = rdman_coord_new(rdman, *coord_pos); | |
282 coord_back->matrix[2] = 25; | |
283 coord_back->matrix[5] = 25; | |
284 rdman_coord_changed(rdman, coord_back); | |
285 | |
286 *coord_rot = rdman_coord_new(rdman, coord_back); | |
287 | |
288 *coord_center = rdman_coord_new(rdman, *coord_rot); | |
289 (*coord_center)->matrix[2] = -25; | |
290 (*coord_center)->matrix[5] = -25; | |
291 rdman_coord_changed(rdman, *coord_center); | |
292 } | |
293 | |
133 void | 294 void |
134 initial_tank(tank_rt_t *tank_rt, X_MB_runtime_t *mb_rt) { | 295 initial_tank(tank_rt_t *tank_rt, X_MB_runtime_t *mb_rt) { |
135 redraw_man_t *rdman; | 296 redraw_man_t *rdman; |
136 mb_tman_t *tman; | 297 /* for map areas */ |
137 mud_t *mud; | 298 mud_t *mud; |
138 brick_t *brick; | 299 brick_t *brick; |
139 rock_t *rock; | 300 rock_t *rock; |
140 bush_t *bush; | 301 bush_t *bush; |
141 mb_word_t *word; | 302 /* for tanks */ |
142 mb_timeval_t start, playing; | 303 coord_t *coord_center, *coord_pos, *coord_rot; |
143 mb_timeval_t mbtv; | 304 tank1_t *tank1_o; |
144 subject_t *comp_sub; | 305 tank2_t *tank2_o; |
145 ob_factory_t *factory; | 306 tank_en_t *tank_en_o; |
146 int i, j; | 307 int i, j; |
147 | 308 |
148 rdman = X_MB_rdman(mb_rt); | 309 rdman = X_MB_rdman(mb_rt); |
149 | 310 |
150 tank_rt->mb_rt = mb_rt; | 311 tank_rt->mb_rt = mb_rt; |
173 break; | 334 break; |
174 } | 335 } |
175 } | 336 } |
176 } | 337 } |
177 | 338 |
178 tank_rt->tank1 = tank1_new(rdman, rdman->root_coord); | 339 make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); |
179 CHANGE_POS(tank_rt->tank1, 5 * 50, 11 * 50); | 340 tank1_o = tank1_new(rdman, coord_center); |
180 tank_rt->tank2 = tank2_new(rdman, rdman->root_coord); | 341 tank_rt->tank1 = tank_new(coord_pos, coord_rot, 5, 11, mb_rt); |
181 CHANGE_POS(tank_rt->tank2, 10 * 50, 11 * 50); | 342 tank_rt->tank1_o = tank1_o; |
343 | |
344 make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); | |
345 tank2_o = tank2_new(rdman, coord_center); | |
346 tank_rt->tank2 = tank_new(coord_pos, coord_rot, 10, 11, mb_rt); | |
347 tank_rt->tank2_o = tank2_o; | |
348 | |
182 for(i = 0; i < 3; i++) { | 349 for(i = 0; i < 3; i++) { |
183 tank_rt->tank_enemies[i] = tank_en_new(rdman, rdman->root_coord); | 350 make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); |
184 CHANGE_POS(tank_rt->tank_enemies[i], (2 + i * 3) * 50, 0); | 351 tank_en_o = tank_en_new(rdman, coord_center); |
352 tank_rt->tank_enemies[i] = tank_new(coord_pos, coord_rot, | |
353 i * 3 + 3, 0, mb_rt); | |
354 tank_rt->tank_enemies_o[i] = tank_en_o; | |
185 } | 355 } |
186 tank_rt->n_enemy = i; | 356 tank_rt->n_enemy = i; |
187 | |
188 tank_rt->tank1_progm = mb_progm_new(4, rdman); | |
189 | |
190 MB_TIMEVAL_SET(&start, 1, 0); | |
191 MB_TIMEVAL_SET(&playing, 3, 0); | |
192 word = mb_progm_next_word(tank_rt->tank1_progm, &start, &playing); | |
193 | |
194 mb_shift_new(0, -150, tank_rt->tank1->root_coord, word); | |
195 mb_shift_new(0, -150, tank_rt->tank2->root_coord, word); | |
196 | |
197 MB_TIMEVAL_SET(&start, 5, 0); | |
198 MB_TIMEVAL_SET(&playing, 3, 0); | |
199 word = mb_progm_next_word(tank_rt->tank1_progm, &start, &playing); | |
200 | |
201 mb_shift_new(0, 150, tank_rt->tank1->root_coord, word); | |
202 mb_shift_new(0, 150, tank_rt->tank2->root_coord, word); | |
203 | |
204 /* Free program after program completed. */ | |
205 comp_sub = mb_progm_get_complete(tank_rt->tank1_progm); | |
206 factory = rdman_get_ob_factory(rdman); | |
207 subject_add_observer(factory, comp_sub, free_progm_handler, tank_rt); | |
208 | |
209 tman = X_MB_tman(mb_rt); | |
210 get_now(&mbtv); | |
211 mb_progm_start(tank_rt->tank1_progm, tman, &mbtv); | |
212 | 357 |
213 init_keyboard(tank_rt); | 358 init_keyboard(tank_rt); |
214 } | 359 } |
215 | 360 |
216 int | 361 int |