void Bullet::process_move() { //-------------- update position -----------------// // // If it gets very close to the destination, fit it // to the destination ingoring the normal vector. // //------------------------------------------------// cur_x = origin_x + (int)(go_x-origin_x) * cur_step / total_step; cur_y = origin_y + (int)(go_y-origin_y) * cur_step / total_step; //cur_step++; //------- update frame id. --------// if( ++cur_frame > cur_sprite_move()->frame_count ) cur_frame = 1; //----- if the sprite has reach the destintion ----// //if( cur_step > total_step ) if( ++cur_step > total_step ) { check_hit(); cur_action = SPRITE_DIE; // Explosion // ###### begin Gilbert 17/5 #########// // if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc if( sprite_info->die.first_frame_recno ) { next_x = cur_x = target_x_loc * ZOOM_LOC_WIDTH; next_y =cur_y = target_y_loc * ZOOM_LOC_HEIGHT; } // ###### end Gilbert 17/5 #########// cur_frame = 1; } else if( total_step - cur_step == 1 ) { warn_target(); } }
void Tornado::process_move() { int speed = weather.wind_speed() / 6; int minSpeed = magic_weather.wind_day > 0 ? 1 : 5; if( speed < minSpeed) speed = minSpeed; if( speed > 10) speed = 10; double windDir = weather.wind_direct_rad() + (misc.random(31)-15)*PI/180.0; cur_x += short(speed * sin(windDir)); cur_y -= short(speed * cos(windDir)); if( ++cur_frame > cur_sprite_move()->frame_count ) cur_frame = 1; // static UCHAR nextFrame[] = { 1,6,1,1,1,1,4 }; // 1->6->4->1 ... // cur_frame = nextFrame[cur_frame]; hit_target(); }
void Sprite::process_move() { #ifdef DEBUG int debugStepMagn1 = move_step_magn(); err_when(abs(cur_x-next_x)>LOCATE_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>LOCATE_HEIGHT*debugStepMagn1); #endif //---- for some sprite (e.g. elephant), move one step per a few frames ----// if( --remain_frames_per_step > 0 ) return; else remain_frames_per_step = sprite_info->frames_per_step; err_when(cur_x < 0 || cur_y < 0 || cur_x >= MAX_WORLD_X_LOC * LOCATE_WIDTH || cur_y >= MAX_WORLD_Y_LOC * LOCATE_HEIGHT); err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y)); //----- if the sprite has reach the destintion ----// if( cur_x==go_x && cur_y==go_y) { cur_action = SPRITE_IDLE; int rc = set_next(cur_x, cur_y); //********* BUGHERE err_when( !rc ); #ifdef DEBUG char h, w, blocked=0; short x, y; for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++) { for(w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++) blocked = world.get_loc(x, y)->unit_recno(mobile_type) != sprite_recno; } err_if(blocked) err_here(); #endif cur_frame = 1; return; } err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y)); //---- set the next tile the sprite will be moving towards ---// static short vector_x_array[] = { 0, 1, 1, 1, 0, -1, -1, -1 }; // default vectors, temporary only static short vector_y_array[] = { -1, -1, 0, 1, 1, 1, 0, -1 }; // short stepX = sprite_info->speed; // short stepY = sprite_info->speed; short stepX, stepY; stepX = stepY = sprite_speed(); if( final_dir & 1 ) // diagonal direction slower { if( stepX >=8 ) { stepY = (stepX -= (unsigned)stepX /4 ); // slightly fast for unsigned division } else if( stepX >= 3 ) { --stepX; --stepY; } } //------------------------------------------// if( next_x != go_x || next_y != go_y ) // if next_x==go_x & next_y==go_y, reach destination already, don't move further. { if( abs(cur_x-next_x) <= stepX && abs(cur_y-next_y) <= stepY ) { int stepMagn = move_step_magn(); if( !set_next(next_x+stepMagn*move_x_pixel_array[final_dir], next_y+stepMagn*move_y_pixel_array[final_dir], -stepMagn) ) return; } } err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y)); //---- if the is blocked, cur_action is changed to SPRITE_WAIT, return now ----// if( cur_action != SPRITE_MOVE ) return; //-------------- update position -----------------// // // If it gets very close to the destination, fit it // to the destination ingoring the normal vector. // //------------------------------------------------// short vectorX = vector_x_array[final_dir] * stepX; // cur_dir may be changed in the above set_next() call short vectorY = vector_y_array[final_dir] * stepY; if( abs(cur_x-go_x) <= stepX ) cur_x = go_x; else cur_x += vectorX; if( abs(cur_y-go_y) <= stepY ) cur_y = go_y; else cur_y += vectorY; err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y)); // is a better checking if speed in all direction is equal #ifdef DEBUG int debugStepMagn2 = move_step_magn(); err_when(abs(cur_x-next_x)>LOCATE_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>LOCATE_HEIGHT*debugStepMagn1); #endif //-------- check boundary ---------// err_when(cur_x < 0 || cur_y < 0 || cur_x >= MAX_WORLD_X_LOC * LOCATE_WIDTH || cur_y >= MAX_WORLD_Y_LOC * LOCATE_HEIGHT); //------- update frame id. --------// if( ++cur_frame > cur_sprite_move()->frame_count ) cur_frame = 1; }
// --------- begin of function BulletHoming::process_move --------// void BulletHoming::process_move() { int actualStep = total_step; if(target_type == BULLET_TARGET_UNIT) { Unit *unitPtr; if( unit_array.is_deleted(target_recno) || !(unitPtr = unit_array[target_recno]) || !unitPtr->is_visible() ) { // target lost/die, proceed to Bullet::process_move target_type = BULLET_TARGET_NONE; } else { // ---- calculate new target_x_loc, target_y_loc -----// target_x_loc = unitPtr->next_x_loc(); target_y_loc = unitPtr->next_y_loc(); // ---- re-calculate go_x, go_y ------// // go_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // it is different from Bullet go_x = unitPtr->cur_x + ZOOM_LOC_WIDTH / 2; go_y = unitPtr->cur_y + ZOOM_LOC_HEIGHT /2; //---------- set bullet movement steps -----------// SpriteFrame *spriteFrame = cur_sprite_frame(); int adjX = spriteFrame->offset_x+spriteFrame->width/2; int adjY = spriteFrame->offset_y+spriteFrame->height/2; int xStep = abs(go_x - (cur_x+adjX))/speed; int yStep = abs(go_y - (cur_y+adjY))/speed; total_step = cur_step + MAX(xStep, yStep); // a homing bullet has a limited range, if the target go outside the // the limit, the bullet can't attack the target // in this case, actualStep is the number step from the source // to the target; total_step is the max_step // otherwise, actualStep is as same as total_step actualStep = total_step; if( total_step > max_step ) { total_step = max_step; // target_x_loc and target_y_loc is limited also target_x_loc = (cur_x + adjX) + (int)(go_x-(cur_x+adjX)) / (actualStep - total_step) / ZOOM_LOC_WIDTH; target_x_loc = (cur_y + adjY) + (int)(go_y-(cur_y+adjY)) / (actualStep - total_step) / ZOOM_LOC_HEIGHT; } } } // origin2_x = origin_x; // origin2_y = origin_y; // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // SpriteFrame *spriteFrame = cur_sprite_frame(); short adjX = spriteFrame->offset_x + spriteFrame->width/2; short adjY = spriteFrame->offset_y + spriteFrame->height/2; origin_x = cur_x + adjX; origin_y = cur_y + adjY; cur_x = origin_x + (int)(go_x-origin_x) / (actualStep + 1 - cur_step); cur_y = origin_y + (int)(go_y-origin_y) / (actualStep + 1 - cur_step); // cur_x, cur_y is temporary pointing at the centre of bullet bitmap // detect changing direction if( cur_step > 3 ) // not allow changing direction so fast set_dir(origin2_x, origin2_y, cur_x, cur_y); // change cur_x, cur_y to bitmap reference point spriteFrame= cur_sprite_frame(); adjX = spriteFrame->offset_x + spriteFrame->width/2; adjY = spriteFrame->offset_y + spriteFrame->height/2; cur_x -= adjX; cur_y -= adjY; cur_step++; //------- update frame id. --------// if( ++cur_frame > cur_sprite_move()->frame_count ) cur_frame = 1; //----- if the sprite has reach the destintion ----// if( cur_step > total_step ) { check_hit(); cur_action = SPRITE_DIE; // Explosion // ###### begin Gilbert 17/5 ########// // if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc if( sprite_info->die.first_frame_recno ) { next_x = cur_x = target_x_loc * ZOOM_LOC_WIDTH; next_y = cur_y = target_y_loc * ZOOM_LOC_HEIGHT; } // ###### end Gilbert 17/5 ########// cur_frame = 1; } // change of total_step may not call warn_target, so call more warn_target else if( total_step - cur_step <= 1 ) { warn_target(); } }