# HG changeset patch # User Thinker K.F. Li # Date 1226970280 -28800 # Node ID 257af0ed58526d25a794847ed5a8e0e430057b2e # Parent a7358d9127c8197e05fb84f64b5c4b4c5a9f7387 When a bullet hits a tank or wall, it shows a bang animation. * Bang is not removed after animation stop. * We want removing program and bang as animation actions. diff -r a7358d9127c8 -r 257af0ed5852 examples/tank/tank_main.c --- a/examples/tank/tank_main.c Fri Nov 07 15:18:22 2008 +0800 +++ b/examples/tank/tank_main.c Tue Nov 18 09:04:40 2008 +0800 @@ -65,6 +65,9 @@ int direction; mb_progm_t *progm; tank_bullet_t *bullet; + struct _tank_rt *tank_rt; /*!< \brief for bullet to check + * hitting on tanks. + */ }; typedef struct _tank tank_t; enum { TD_UP = 0, TD_RIGHT, TD_DOWN, TD_LEFT }; @@ -94,7 +97,7 @@ static tank_t *tank_new(coord_t *coord_pos, coord_t *coord_rot, int map_x, int map_y, - X_MB_runtime_t *mb_rt) { + tank_rt_t *tank_rt) { tank_t *tank; redraw_man_t *rdman; @@ -102,7 +105,7 @@ if(tank == NULL) return NULL; - rdman = X_MB_rdman(mb_rt); + rdman = X_MB_rdman(tank_rt->mb_rt); tank->coord_pos = coord_pos; tank->coord_rot = coord_rot; @@ -111,6 +114,7 @@ tank->direction = TD_UP; tank->progm = NULL; tank->bullet = NULL; + tank->tank_rt = tank_rt; memset(coord_pos->matrix, 0, sizeof(co_aix[6])); coord_pos->matrix[0] = 1; @@ -317,16 +321,6 @@ 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; - - bullet = tank->bullet; - mb_progm_free(bullet->progm); - 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; @@ -341,18 +335,53 @@ coord_hide(bullet->coord_pos); rdman_coord_changed(rdman, bullet->coord_pos); - /*! \todo Simplify the procdure of using observer pattern. */ - - bullet_go_out_map_and_redraw(NULL, tank); + bullet = tank->bullet; + mb_progm_free(bullet->progm); + tank_bullet_free(tank->bullet); + tank->bullet = NULL; } static void bullet_bang(tank_bullet_t *bullet, int map_x, int map_y) { + redraw_man_t *rdman; + mb_tman_t *tman; + mb_progm_t *progm; + mb_word_t *word; + mb_timeval_t start, playing; + mb_timeval_t now; + bang_t *bang; + co_aix *matrix; + + rdman = bullet->rdman; + tman = bullet->tman; + + bang = bang_new(rdman, rdman->root_coord); + matrix = bang->root_coord->matrix; + matrix[2] = map_x * 50; + matrix[5] = map_y * 50; + rdman_coord_changed(rdman, bang->root_coord); + + progm = mb_progm_new(3, rdman); + + MB_TIMEVAL_SET(&start, 1, 0); + MB_TIMEVAL_SET(&playing, 0, 0); + word = mb_progm_next_word(progm, &start, &playing); + mb_visibility_new(VIS_HIDDEN, bang->root_coord, word); + + MB_TIMEVAL_SET(&start, 1, 500000); + word = mb_progm_next_word(progm, &start, &playing); + mb_visibility_new(VIS_VISIBLE, bang->root_coord, word); + + /*! \todo Remove bang and program when program stops. */ + get_now(&now); + mb_progm_start(progm, tman, &now); } static void bullet_hit_chk(const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { tank_t *tank = (tank_t *)arg; + tank_rt_t *tank_rt = tank->tank_rt; + tank_t *tank_hitted; tank_bullet_t *bullet; mb_timeval_t diff, next; mb_timeval_t unit_tm; @@ -360,9 +389,14 @@ int move_units; int x, y; int dir; + int i; static int move_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; bullet = tank->bullet; + bullet->hit_tmr = NULL; /* clear hit timer that bullet_go_out_map() + * can not remove it & currupt memory. + */ + MB_TIMEVAL_CP(&diff, now); MB_TIMEVAL_DIFF(&diff, &bullet->start_time); MB_TIMEVAL_SET(&unit_tm, 0, 250000); @@ -373,16 +407,52 @@ y = bullet->start_map_y + move_adj[dir][1] * move_units; if(map[y][x] != MUD) { - bullet->hit_tmr = NULL; mb_progm_abort(bullet->progm); - bullet_go_out_map(NULL, arg); + bullet_go_out_map(NULL, tank); bullet_bang(bullet, x, y); - } else { - MB_TIMEVAL_SET(&next, 0, 100000); - MB_TIMEVAL_ADD(&next, now); - bullet->hit_tmr = mb_tman_timeout(bullet->tman, &next, - bullet_hit_chk, arg); + return; + } + + /*! \todo Move tanks into a list. */ + for(i = 0; i < tank_rt->n_enemy; i++) { + tank_hitted = tank_rt->tank_enemies[i]; + if(tank_hitted == tank) + continue; + if(tank_hitted->map_x == x && + tank_hitted->map_y == y) { + mb_progm_abort(bullet->progm); + bullet_go_out_map(NULL, tank); + bullet_bang(bullet, x, y); + return; + } } + + if(tank_rt->tank1 != tank) { + tank_hitted = tank_rt->tank1; + if(tank_hitted->map_x == x && + tank_hitted->map_y == y) { + mb_progm_abort(bullet->progm); + bullet_go_out_map(NULL, tank); + bullet_bang(bullet, x, y); + return; + } + } + + if(tank_rt->tank2 != tank) { + tank_hitted = tank_rt->tank2; + if(tank_hitted->map_x == x && + tank_hitted->map_y == y) { + mb_progm_abort(bullet->progm); + bullet_go_out_map(NULL, tank); + bullet_bang(bullet, x, y); + return; + } + } + + MB_TIMEVAL_SET(&next, 0, 100000); + MB_TIMEVAL_ADD(&next, now); + bullet->hit_tmr = mb_tman_timeout(bullet->tman, &next, + bullet_hit_chk, arg); } static void tank_fire_bullet(tank_rt_t *tank_rt, tank_t *tank) { @@ -450,6 +520,7 @@ act = mb_shift_new(shift_x, shift_y, bullet->coord_pos, word); bullet->progm = progm; + /*! \todo Simplify the procdure of using observer pattern. */ subject = mb_progm_get_complete(progm); factory = rdman_get_ob_factory(rdman); subject_add_observer(factory, subject, bullet_go_out_map, tank); @@ -593,19 +664,19 @@ make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); tank1_o = tank1_new(rdman, coord_center); - tank_rt->tank1 = tank_new(coord_pos, coord_rot, 5, 11, mb_rt); + tank_rt->tank1 = tank_new(coord_pos, coord_rot, 5, 11, tank_rt); tank_rt->tank1_o = tank1_o; make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); tank2_o = tank2_new(rdman, coord_center); - tank_rt->tank2 = tank_new(coord_pos, coord_rot, 10, 11, mb_rt); + tank_rt->tank2 = tank_new(coord_pos, coord_rot, 10, 11, tank_rt); tank_rt->tank2_o = tank2_o; for(i = 0; i < 3; i++) { make_elf_coords(rdman, &coord_pos, &coord_rot, &coord_center); tank_en_o = tank_en_new(rdman, coord_center); tank_rt->tank_enemies[i] = tank_new(coord_pos, coord_rot, - i * 3 + 3, 0, mb_rt); + i * 3 + 3, 0, tank_rt); tank_rt->tank_enemies_o[i] = tank_en_o; tank_rt->tanks[i] = tank_rt->tank_enemies[i]; } diff -r a7358d9127c8 -r 257af0ed5852 include/mb_types.h --- a/include/mb_types.h Fri Nov 07 15:18:22 2008 +0800 +++ b/include/mb_types.h Tue Nov 18 09:04:40 2008 +0800 @@ -20,7 +20,7 @@ * the paint. * * \todo move member functions to a seperate structure and setup a - * singleton fro each paint type. + * singleton for each paint type. */ struct _paint { int flags; @@ -118,8 +118,6 @@ int num_members; STAILQ(geo_t) members; /*!< \brief All geo_t members in this coord. */ - STAILQ(shape_t) shapes; /*!< \brief All shapes managed by the rdman. */ - subject_t *mouse_event; } coord_t; #define COF_DIRTY 0x1 diff -r a7358d9127c8 -r 257af0ed5852 src/redraw_man.c --- a/src/redraw_man.c Fri Nov 07 15:18:22 2008 +0800 +++ b/src/redraw_man.c Tue Nov 18 09:04:40 2008 +0800 @@ -649,8 +649,10 @@ add_dirty_coord(rdman, coord); +#if 0 if(coord->flags & COF_HIDDEN) return OK; +#endif /* Make child coords dirty. */ for(child = preorder_coord_subtree(coord, coord); @@ -912,6 +914,9 @@ static void draw_shape(redraw_man_t *rdman, cairo_t *cr, shape_t *shape) { paint_t *fill, *stroke; + /*! \todo Move operator of shapes into singleton structures that define + * operators for them. + */ if(shape->fill || shape->stroke) { switch(shape->sh_type) { case SHT_PATH: