Mercurial > MadButterfly
changeset 154:6ce68c1f7405
Tank can fire bullet.
1. Add the redraw subject on redraw_man_t.
2. mb_c_source.m4 & mb_c_header.m4 are changed to free & remove shapes.
3. Add rdman_coord_subtree_free() to remove a subtree of coords.
4. Fix bug of rdman_remove_shape().
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Tue, 30 Sep 2008 02:44:06 +0800 |
parents | 9870b049b7f6 |
children | 6749f6639924 |
files | dox/first_program.h examples/tank/tank_main.c src/observer.h src/paint.c src/redraw_man.c src/redraw_man.h src/shift.c tools/mb_c_header.m4 tools/mb_c_source.m4 |
diffstat | 9 files changed, 287 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/dox/first_program.h Sat Sep 27 02:40:42 2008 +0800 +++ b/dox/first_program.h Tue Sep 30 02:44:06 2008 +0800 @@ -16,9 +16,9 @@ * programs. * * For example, to translate foo.svg with steps - * - $(PREFIX)/bin/svg2code.py foo.svg foo.mb - * - m4 -I $(PREFIX)/share/mb mb_c_source.m4 foo.mb > foo.c - * - m4 -I $(PREFIX)/share/mb mb_c_header.m4 foo.mb > foo.h + * - \$(PREFIX)/bin/svg2code.py foo.svg foo.mb + * - m4 -I \$(PREFIX)/share/mb mb_c_source.m4 foo.mb > foo.c + * - m4 -I \$(PREFIX)/share/mb mb_c_header.m4 foo.mb > foo.h * * foo.h declares a structure, named 'foo' and two functions, * foo_new() and foo_free(). An instance of 'foo' holds all objects for
--- a/examples/tank/tank_main.c Sat Sep 27 02:40:42 2008 +0800 +++ b/examples/tank/tank_main.c Tue Sep 30 02:44:06 2008 +0800 @@ -40,17 +40,32 @@ * \brief Tank elf module provides control functions of tanks in game. * @{ */ +struct _tank_bullet { + redraw_man_t *rdman; + coord_t *coord_pos; + coord_t *coord_rot; + bullet_t *bullet_obj; + int start_map_x, start_map_y; + int direction; + mb_progm_t *progm; + mb_timeval_t start_time; + observer_t *ob_redraw; +}; +typedef struct _tank_bullet tank_bullet_t; +enum { BU_UP = 0, BU_RIGHT, BU_DOWN, BU_LEFT }; + struct _tank { coord_t *coord_pos; /*!< \brief coordinate for position */ coord_t *coord_rot; /*!< \brief coordinate for rotation */ + coord_t *coord_center; int map_x, map_y; int direction; mb_progm_t *progm; + tank_bullet_t *bullet; }; typedef struct _tank tank_t; enum { TD_UP = 0, TD_RIGHT, TD_DOWN, TD_LEFT }; - /* @} */ typedef struct _tank_rt tank_rt_t; @@ -92,6 +107,7 @@ tank->map_y = map_y; tank->direction = TD_UP; tank->progm = NULL; + tank->bullet = NULL; memset(coord_pos->matrix, 0, sizeof(co_aix[6])); coord_pos->matrix[0] = 1; @@ -233,6 +249,174 @@ /* @} */ +/*! \brief Make coord objects for bullet elfs. */ +static void make_bullet_elf_coords(redraw_man_t *rdman, coord_t **coord_pos, + coord_t **coord_rot, + coord_t **coord_center) { + coord_t *coord_back; + + *coord_pos = rdman_coord_new(rdman, rdman->root_coord); + + coord_back = rdman_coord_new(rdman, *coord_pos); + coord_back->matrix[2] = 25; + coord_back->matrix[5] = 25; + rdman_coord_changed(rdman, coord_back); + + *coord_rot = rdman_coord_new(rdman, coord_back); + + *coord_center = rdman_coord_new(rdman, *coord_rot); + (*coord_center)->matrix[2] = -5; + (*coord_center)->matrix[5] = +15; + rdman_coord_changed(rdman, *coord_center); +} + +static tank_bullet_t *tank_bullet_new(redraw_man_t *rdman, + int map_x, int map_y, + int direction) { + tank_bullet_t *bullet; + coord_t *coord_center; + co_aix *matrix; + static float _sins[] = { 0, 1, 0, -1}; + static float _coss[] = { 1, 0, -1, 0}; + float _sin, _cos; + + bullet = O_ALLOC(tank_bullet_t); + bullet->rdman = rdman; + + make_bullet_elf_coords(rdman, &bullet->coord_pos, + &bullet->coord_rot, + &coord_center); + bullet->bullet_obj = bullet_new(rdman, coord_center); + + bullet->start_map_x = map_x; + bullet->start_map_y = map_y; + bullet->direction = direction; + bullet->progm = NULL; + + matrix = bullet->coord_pos->matrix; + matrix[2] = map_x * 50; + matrix[5] = map_y * 50; + rdman_coord_changed(rdman, bullet->coord_pos); + + _sin = _sins[direction]; + _cos = _coss[direction]; + matrix = bullet->coord_rot->matrix; + matrix[0] = _cos; + matrix[1] = -_sin; + matrix[3] = _sin; + matrix[4] = _cos; + + return bullet; +} + +static void tank_bullet_free(tank_bullet_t *bullet) { + bullet_free(bullet->bullet_obj); + rdman_coord_subtree_free(bullet->rdman, bullet->coord_pos); +} + +static void bullet_go_out_map_and_redraw(event_t *event, void *arg) { + tank_t *tank = (tank_t *)arg; + tank_bullet_t *bullet; + ob_factory_t *factory; + subject_t *redraw; + + bullet = tank->bullet; + mb_progm_free(bullet->progm); + rdman_force_clean(bullet->rdman); + factory = rdman_get_ob_factory(bullet->rdman); + redraw = rdman_get_redraw_subject(bullet->rdman); + subject_remove_observer(factory, redraw, bullet->ob_redraw); + tank_bullet_free(tank->bullet); + tank->bullet = NULL; +} + +static void bullet_go_out_map(event_t *event, void *arg) { + tank_t *tank = (tank_t *)arg; + tank_bullet_t *bullet; + redraw_man_t *rdman; + subject_t *redraw; + ob_factory_t *factory; + + /*! \todo Simplify the procdure of using observer pattern. */ + bullet = tank->bullet; + rdman = bullet->rdman; + factory = rdman_get_ob_factory(rdman); + redraw = rdman_get_redraw_subject(rdman); + bullet->ob_redraw = + subject_add_observer(factory, redraw, + bullet_go_out_map_and_redraw, tank); +} + +static void tank_fire_bullet(tank_rt_t *tank_rt, tank_t *tank) { + X_MB_runtime_t *xmb_rt; + redraw_man_t *rdman; + int map_x, map_y; + int shift_x, shift_y; + int shift_len; + int dir; + tank_bullet_t *bullet; + mb_progm_t *progm; + mb_word_t *word; + mb_action_t *act; + mb_timeval_t start, playing; + mb_timeval_t now; + ob_factory_t *factory; + mb_tman_t *tman; + subject_t *subject; + static int map_xy_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; + + if(tank->bullet != NULL) + return; + + xmb_rt = tank_rt->mb_rt; + rdman = X_MB_rdman(xmb_rt); + tman = X_MB_tman(xmb_rt); + + dir = tank->direction; + map_x = tank->map_x + map_xy_adj[dir][0]; + map_y = tank->map_y + map_xy_adj[dir][1]; + tank->bullet = tank_bullet_new(rdman, map_x, map_y, dir); + bullet = tank->bullet; + + switch(dir) { + case TD_UP: + shift_len = map_y + 1; + shift_x = 0; + shift_y = -shift_len * 50; + break; + case TD_RIGHT: + shift_len = 16 - map_x; + shift_x = shift_len * 50; + shift_y = 0; + break; + case TD_DOWN: + shift_len = 12 - map_y; + shift_x = 0; + shift_y = shift_len * 50; + break; + case TD_LEFT: + shift_len = map_x + 1; + shift_x = -shift_len * 50; + shift_y = 0; + break; + } + + progm = mb_progm_new(2, rdman); + MB_TIMEVAL_SET(&start, 0, 0); + MB_TIMEVAL_SET(&playing, shift_len / 4, (shift_len % 4) * 250000); + word = mb_progm_next_word(progm, &start, &playing); + act = mb_shift_new(shift_x, shift_y, bullet->coord_pos, word); + bullet->progm = progm; + + subject = mb_progm_get_complete(progm); + factory = rdman_get_ob_factory(rdman); + subject_add_observer(factory, subject, bullet_go_out_map, tank); + + get_now(&now); + MB_TIMEVAL_CP(&bullet->start_time, &now); + mb_progm_start(progm, tman, &now); +} + #define CHANGE_POS(g, x, y) do { \ (g)->root_coord->matrix[0] = 1.0; \ (g)->root_coord->matrix[2] = x; \ @@ -271,6 +455,7 @@ break; case 0x20: /* space */ + tank_fire_bullet(tank_rt, tank_rt->tank1); break; case 0xff0d: /* enter */ default:
--- a/src/observer.h Sat Sep 27 02:40:42 2008 +0800 +++ b/src/observer.h Tue Sep 30 02:44:06 2008 +0800 @@ -42,7 +42,7 @@ #define SUBF_BUSY 0x2 /*!< \brief in subject_notify() */ #define SUBF_FREE 0x4 /*!< \brief in postponding subject_free() */ -enum {OBJT_GEO, OBJT_COORD, OBJT_KB, OBJT_PROGM}; +enum {OBJT_GEO, OBJT_COORD, OBJT_KB, OBJT_PROGM, OBJT_RDMAN}; struct _mouse_event { event_t event; @@ -72,7 +72,8 @@ enum {EVT_MOUSE_OVER, EVT_MOUSE_OUT, EVT_MOUSE_MOVE, EVT_MOUSE_BUT_PRESS, EVT_MOUSE_BUT_RELEASE, - EVT_KB_PRESS, EVT_KB_RELEASE, EVT_PROGM_COMPLETE}; + EVT_KB_PRESS, EVT_KB_RELEASE, EVT_PROGM_COMPLETE, + EVT_RDMAN_REDRAW }; extern subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type);
--- a/src/paint.c Sat Sep 27 02:40:42 2008 +0800 +++ b/src/paint.c Tue Sep 30 02:44:06 2008 +0800 @@ -26,7 +26,7 @@ paint_color_t *color = (paint_color_t *)paint; shnode_list_free(color->rdman, paint->members); - free(paint); + elmpool_elm_free(color->rdman->paint_color_pool, paint); } paint_t *paint_color_new(redraw_man_t *rdman,
--- a/src/redraw_man.c Sat Sep 27 02:40:42 2008 +0800 +++ b/src/redraw_man.c Tue Sep 30 02:44:06 2008 +0800 @@ -271,6 +271,9 @@ rdman->ob_factory.observer_free = ob_observer_free; rdman->ob_factory.get_parent_subject = ob_get_parent_subject; + rdman->redraw = + subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); + rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); if(rdman->root_coord == NULL) redraw_man_destroy(rdman); @@ -364,7 +367,9 @@ /*! \brief Remove a shape object from redraw manager. * + * \note Shapes should be removed after redrawing or when rdman is in clean. * \todo redraw shape objects that overlaid with removed one. + * \todo To allow shapes be removed at anytime. */ int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { geo_t *geo; @@ -375,7 +380,7 @@ geo_detach_coord(geo, coord); subject_free(&rdman->ob_factory, geo->mouse_event); sh_detach_geo(shape); - elmpool_elm_free(rdman->geo_pool, shape->geo); + elmpool_elm_free(rdman->geo_pool, geo); sh_detach_coord(shape); return OK; } @@ -449,6 +454,29 @@ return OK; } +int rdman_coord_subtree_free(redraw_man_t *rdman, coord_t *subtree) { + coord_t *coord, *prev_coord; + int r; + + if(subtree == NULL) + return OK; + + prev_coord = postorder_coord_subtree(subtree, NULL); + for(coord = postorder_coord_subtree(subtree, prev_coord); + coord != NULL; + coord = postorder_coord_subtree(subtree, coord)) { + r = rdman_coord_free(rdman, prev_coord); + if(r != OK) + return ERR; + prev_coord = coord; + } + r = rdman_coord_free(rdman, prev_coord); + if(r != OK) + return ERR; + + return OK; +} + /*! \brief Mark a coord is changed. * * A changed coord_t object is marked as dirty and put @@ -921,6 +949,9 @@ int r; int n_dirty_areas; area_t **dirty_areas; + event_t event; + ob_factory_t *factory; + subject_t *redraw; r = clean_rdman_dirties(rdman); if(r != OK) @@ -940,6 +971,12 @@ } rdman->n_dirty_areas = 0; + factory = rdman_get_ob_factory(rdman); + redraw = rdman_get_redraw_subject(rdman); + event.type = EVT_RDMAN_REDRAW; + event.tgt = event.cur_tgt = redraw; + subject_notify(factory, redraw, &event); + return OK; }
--- a/src/redraw_man.h Sat Sep 27 02:40:42 2008 +0800 +++ b/src/redraw_man.h Tue Sep 30 02:44:06 2008 +0800 @@ -55,6 +55,8 @@ cairo_t *backend; ob_factory_t ob_factory; + + subject_t *redraw; /*!< \brief Notified after redrawing. */ } redraw_man_t; extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, @@ -68,6 +70,7 @@ extern int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape); extern coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent); extern int rdman_coord_free(redraw_man_t *rdman, coord_t *coord); +extern int rdman_coord_subtree_free(redraw_man_t *rdman, coord_t *subtree); extern int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord); extern int rdman_shape_changed(redraw_man_t *rdman, shape_t *shape); extern int rdman_redraw_changed(redraw_man_t *rdman); @@ -116,6 +119,7 @@ extern shape_t *find_shape_at_pos(redraw_man_t *rdman, co_aix x, co_aix y, int *in_stroke); #define rdman_get_ob_factory(rdman) (&(rdman)->ob_factory) +#define rdman_get_redraw_subject(rdman) ((rdman)->redraw) #endif /* __REDRAW_MAN_H_ */
--- a/src/shift.c Sat Sep 27 02:40:42 2008 +0800 +++ b/src/shift.c Tue Sep 30 02:44:06 2008 +0800 @@ -91,6 +91,7 @@ shift->action.stop = mb_shift_stop; shift->action.free = mb_shift_free; + /*! \note mb_shift_new() will add itself to the specified word. */ mb_word_add_action(word, (mb_action_t *)shift); return (mb_action_t *)shift;
--- a/tools/mb_c_header.m4 Sat Sep 27 02:40:42 2008 +0800 +++ b/tools/mb_c_header.m4 Tue Sep 30 02:44:06 2008 +0800 @@ -48,6 +48,7 @@ typedef struct $1 $1_t; struct $1 { + redraw_man_t *rdman; coord_t *root_coord;] $2[]dnl [};
--- a/tools/mb_c_source.m4 Sat Sep 27 02:40:42 2008 +0800 +++ b/tools/mb_c_source.m4 Tue Sep 30 02:44:06 2008 +0800 @@ -213,14 +213,17 @@ ]]) define([F_ADD_PATH],[[ + rdman_remove_shape(rdman, obj->$1); obj->$1->free(obj->$1); ]]) define([F_ADD_RECT],[[ + rdman_remove_shape(rdman, obj->$1); obj->$1->free(obj->$1); ]]) define([F_ADD_TEXT],[[ + rdman_remove_shape(rdman, obj->$1); obj->$1->free(obj->$1); ]]) @@ -257,6 +260,42 @@ define([SHAPE_MATRIX],) divert[]]) +define([REVERSE_VARS],[divert([-1]) +define([__REV_VAR],[]) +define([PUSH_REV], [ + pushdef([__REV_VAR]) + define([__REV_VAR], ]QUOTE(QUOTE($[]1))[)]) +define([POP_ALL_REV], [dnl +ifelse(__REV_VAR, [], ,[UNQUOTE(__REV_VAR)[]dnl +popdef([__REV_VAR])[]POP_ALL_REV[]])]) +define([RIMPORT], [ + define(]QUOTE($[]1)[, + [PUSH_REV(]]QUOTE(QUOTE($[]1))[[(]QUOTE($[]@)[))]) +]) +RIMPORT([ADD_LINEAR_PAINT]) +RIMPORT([ADD_RADIAL_PAINT]) +RIMPORT([COLOR_STOP]) +RIMPORT([REF_STOPS_RADIAL]) +RIMPORT([REF_STOPS_LINEAR]) +RIMPORT([ADD_PATH]) +RIMPORT([ADD_RECT]) +RIMPORT([ADD_COORD]) +RIMPORT([ADD_TEXT]) +RIMPORT([FILL_SHAPE]) +RIMPORT([STROKE_SHAPE]) +RIMPORT([FILL_SHAPE_WITH_PAINT]) +RIMPORT([STROKE_SHAPE_WITH_PAINT]) +RIMPORT([STROKE_WIDTH]) +RIMPORT([GROUP_HIDE]) +RIMPORT([RECT_HIDE]) +RIMPORT([PATH_HIDE]) +RIMPORT([COORD_TRANSLATE]) +RIMPORT([COORD_MATRIX]) +RIMPORT([SHAPE_TRANSLATE]) +RIMPORT([SHAPE_MATRIX]) +divert[]dnl +]) + define([MADBUTTERFLY],[dnl [#include <stdio.h> #include <stdlib.h> @@ -274,6 +313,7 @@ [ obj = ($1_t *)malloc(sizeof($1_t)); if(obj == NULL) return NULL; + obj->rdman = rdman; ]SETUP_VARS obj->root_coord = rdman_coord_new(rdman, parent_coord); $2 @@ -282,7 +322,16 @@ void $1_free($1_t *obj) { grad_stop_t *stops = NULL; -]CLEAR_VARS[]$2[ + redraw_man_t *rdman; + + rdman = obj->rdman; +]REVERSE_VARS[]dnl +divert([-1])dnl +$2[]dnl +divert[]dnl +CLEAR_VARS[]dnl +POP_ALL_REV[ + rdman_coord_subtree_free(rdman, obj->root_coord); free(obj); } ]dnl