/** adds force depending on health **/ void Movement::add_force(float forcemultiplierx, float forcemultipliery) { force_x += ((base_parent->health / 100.f) + 1) * forcemultiplierx; gravity += ((base_parent->health / 100.f) + 1) * forcemultipliery; pos.x += force_x; pos.y += gravity; if (grabbing_edge) { grabbing_edge = false; edge_node->edgeempty = true; edge_node = nullptr; update_move(moves.JUMP, 10, false); } rotation = 0; update_move(moves.HIT, 5, false); //restrict_input_x = true; //restrict_input_y = true; }
void AGENT::update(void) { // move if ((!group->is_single_unit() || state == AGENT::READY_FIGHT) && !group->is_building()) { update_move(); collision_check(); } // generic unit status check_health(); if (!has_not_moved()) clear_stuckcounter(); if (!build_data) updateAnimation(); }
Fighter::Fighter(int x, int y, int c_player_id, int c_id, FighterName f_name, FighterType f_type) : Movement(this), Damage(this) { //setup the moves from the inputted fighter texture = new Texture(); switch (f_name) { case CAPTAIN_FALCON: moves = CaptainFalcon(); moves.name = CAPTAIN_FALCON; texture->create_texture(universe->assets->fighter_sheets[0]->s); width = 64; height = 64; offset_y = 2; break; case THOR: moves = Thor(); moves.name = THOR; texture->create_texture(universe->assets->fighter_sheets[1]->s); width = 75; height = 75; offset_x = -16; offset_y = -16; break; } player_id = c_player_id; id = c_id; pos.x = x; pos.y = y; name = f_name; type = f_type; respawning = false; invincible = false; enable_camera_view = true; animator = new Animator(texture, &src_rect, 64, 64, 5, true, true); update_move(moves.JUMP, 10, false); alpha_colour = 0; r = 1; g = 1; b = 1; if (id == 1) { r = 0; g = .5f; b = 1; }else if (id == 2) { r = 1; g = .5f; b = 0; }else if (id == 3) { r = 0; g = 1; b = .5f; } texture->set_colour(r, g, b, 1); blood_particles = universe->particles->create_particle_chunk( new ParticleEmitter(pos.x + 80, pos.y + 64, 10, 1, 4, false), BLOOD); blood_particles->max_particles = 0; }
/** updates the movement **/ void Movement::update_movement() { /** ------------------------------------------------------------------------------------------ GET COORDS ------------------------------------------------------------------------------------------ **/ rect.w = base_parent->width; rect.h = base_parent->height; //update coords based on position and tile size coords.x = (pos.x * base_universe->camera->scale) / base_universe->camera->grid_size; coords.y = (pos.y * base_universe->camera->scale) / base_universe->camera->grid_size; //make sure the coords don't go out of the grid boundaries if (coords.x < 0) { coords.x = 0; }else if (coords.x >= base_universe->map->grid_width - 1) { coords.x = base_universe->map->grid_width - 1; } if (coords.y < 0) { coords.y = 0; }else if (coords.y >= base_universe->map->grid_height - 1) { coords.y = base_universe->map->grid_height - 1; } //get the current node based on the coords Node* node = base_universe->map->nodes[(int)coords.x][(int)coords.y]; /** ------------------------------------------------------------------------------------------ LEFT/RIGHT MOVEMENT + COLLISION ------------------------------------------------------------------------------------------ **/ //apply movement to speedx if the right key or left key is down if (current_move != moves.CROUCH && !grabbing_edge && !restrict_input_x) { if (right_key->down) { speed_x += move_speed; if (floor_collided) { flip = SDL_RendererFlip::SDL_FLIP_NONE; } }else if (left_key->down) { speed_x -= move_speed; if (floor_collided) { flip = SDL_RendererFlip::SDL_FLIP_HORIZONTAL; } } } floor_collided = false; right_collided = false; left_collided = false; roof_collided = false; //check for left and right tile collision if ((node = Collision::collide_right(coords.x, coords.y)) && node->solid) { //snap against right solid tile if (speed_x >= 0) { speed_x = 0; force_x = 0; pos.x = ((int)coords.x + .5f) * 32; } right_collided = true; }else if ((node = Collision::collide_left(coords.x, coords.y)) && node->solid) { //snap against left solid tile if (speed_x <= 0) { speed_x = 0; force_x = 0; pos.x = ((int)coords.x + .5f) * 32; } left_collided = true; } //limit speedx from going over the max speed if (speed_x >= max_speed) { speed_x = max_speed; }else if (speed_x <= -max_speed) { speed_x = -max_speed; } //apply friction to speedx speed_x = speed_x * friction; /** ------------------------------------------------------------------------------------------ EDGE GRABBING ------------------------------------------------------------------------------------------ **/ //check to see if you can collide down on the tile for an edge grab as well as a non solid tile below if (right_collided && !grabbing_edge && gravity >= 0 && (node = Collision::collide_down(coords.x + 1, coords.y - 1)) && node->solid && node->edgeempty && Collision::collide_down(coords.x, coords.y) == NULL && Collision::collide_down(coords.x + 1, coords.y - 2) == NULL && Collision::collide_down(coords.x, coords.y - 1) == NULL) { //snap against the tile in x and y and reset variables gravity = 0; rotation = 0; speed_x = 0; force_x = 0; pos.x = ((int)coords.x + .5f) * 32; pos.y = ((int)coords.y + 1) * 32; update_move(moves.EDGE_GRAB, 1, false); grabbing_edge = true; double_jump = false; flip = SDL_RendererFlip::SDL_FLIP_NONE; edge_node = node; edge_node->edgeempty = false; }else if (left_collided && !grabbing_edge && gravity >= 0 && (node = Collision::collide_down(coords.x - 1, coords.y - 1)) && node->solid && node->edgeempty && Collision::collide_down(coords.x, coords.y) == NULL && Collision::collide_down(coords.x - 1, coords.y - 2) == NULL && Collision::collide_down(coords.x, coords.y - 1) == NULL) { //snap against the tile in x and y and reset variables gravity = 0; rotation = 0; speed_x = 0; force_x = 0; pos.x = ((int)coords.x + .5f) * 32; if (moves.name == THOR) { pos.x += 14; } pos.y = ((int)coords.y + 1) * 32; update_move(moves.EDGE_GRAB, 1, false); grabbing_edge = true; double_jump = false; flip = SDL_RendererFlip::SDL_FLIP_HORIZONTAL; edge_node = node; edge_node->edgeempty = false; } if (grabbing_edge) { update_move(moves.EDGE_GRAB, 1, false); //if the up key or down key is pressed while holding onto an edge if (up_key->pressed && !restrict_input_y) { //if the up key is down then apply a small initial jump and let go of the edge gravity = -jump_height / 1.5f; holding_jump = true; update_move(moves.JUMP, 10, false); grabbing_edge = false; up_key->pressed = false; edge_node->edgeempty = true; edge_node = nullptr; }else if (down_key->pressed && !restrict_input_y) { //if the down key is down then change moves, reset gravity and let go of the edge gravity = 0; update_move(moves.JUMP, 10, false); grabbing_edge = false; edge_node->edgeempty = true; edge_node = nullptr; } } /** ------------------------------------------------------------------------------------------ GRAVITY + Y COLLIDE + JUMP ------------------------------------------------------------------------------------------ **/ //apply gravity and collide_ downwards and upwards with solid tiles floor_collided = false; if (!grabbing_edge) { if (gravity > 0) { //if the gravity is greater than 0, try colliding downwards if ((node = Collision::collide_down(coords.x, coords.y)) && node->solid) { //snap to bottom tile and reset variables rotation = 0; gravity = 0; pos.y = (int)coords.y * 32; double_jump = false; floor_collided = true; //play the landing animation after jumping or landing if (current_move == moves.AIR_LAND || current_move == moves.JUMP || current_move == moves.LAND) { update_move(moves.LAND, 10, false); }else if (down_air_kick && moves.name == THOR) { update_move(moves.HAMMER_SLAM, 20, false, true); double_jump = false; restrict_input_x = true; restrict_input_y = true; down_air_kick = false; down_hammer_slam = true; base_parent->dealt_damage = false; } //if not doing other actions, idle if speed is low and start running if the speed is fast if (current_move != moves.JUMP && current_move != moves.EDGE_GRAB) { if (current_move != moves.CROUCH || (current_move == moves.CROUCH && !down_key->down)) { if (speed_x >= 1 || speed_x <= -1) { update_move(moves.RUN, moves.RUN_FPS, true); }else if (current_move != moves.LAND && current_move != moves.HIT) { update_move(moves.IDLE, 5, true); } } } //change to idle after the landing animation has finished if (animator->paused && current_move == moves.LAND) { update_move(moves.IDLE, 5, true); } } //change the move to jump when walked off solid platform if (!floor_collided) { if (current_move == moves.IDLE || current_move == moves.RUN || current_move == moves.CROUCH || current_move == moves.DASH_ATTACK || current_move == moves.SLIDE_ATTACK) { update_move(moves.JUMP, 10, false); } } } //limit gravity to the max fall speed if (down_air_kick && moves.name == THOR) { gravity += fall_speed * 4; if (gravity >= max_fall_speed * 2) { gravity = max_fall_speed * 2; } }else { gravity += fall_speed; if (gravity >= max_fall_speed) { gravity = max_fall_speed; } } //if the gravity is less than 0 and colliding up with a solid tile, then snap to the tile if (gravity < 0 && (node = Collision::collide_up(coords.x, coords.y)) && node->solid) { gravity = 0; pos.y = ((int)coords.y + 1) * 32; roof_collided = true; } } /** ------------------------------------------------------------------------------------------ JUMPING ------------------------------------------------------------------------------------------ **/ //if the up key is down then apply a small initial jump and change move if (floor_collided) { if (up_key->pressed && !restrict_input_y) { gravity = -jump_height / 8; holding_jump = true; up_key->pressed = false; update_move(moves.JUMP, 10, false); } } //double jumps and hold for higher jumps if (up_key->down && !restrict_input_y && !roof_collided) { //if the up key is down after jumping once then apply a double jump if (up_key->pressed && !double_jump) { gravity = -jump_height / 8; holding_jump = true; double_jump = true; update_move(moves.DOUBLE_JUMP, 15, false); } //makes jump longer as long as up key is down or until the jump height limit is reached if (holding_jump) { gravity -= fall_speed * 4; if (gravity <= -jump_height) { holding_jump = false; } } }else { holding_jump = false; } //apply rotation to double jump depending on direction if (current_move == moves.DOUBLE_JUMP) { if (!grabbing_edge && current_move == moves.DOUBLE_JUMP && moves.name == THOR && gravity > 0) { update_move(moves.AIR_LAND, moves.AIR_LAND_FPS, false); animator->next_frame(); } if (moves.name == CAPTAIN_FALCON) { if (flip == SDL_RendererFlip::SDL_FLIP_NONE) { rotation -= 40; }else { rotation += 40; } } }else if (!grabbing_edge && current_move == moves.JUMP && gravity > 0) { update_move(moves.AIR_LAND, moves.AIR_LAND_FPS, false); } /** ------------------------------------------------------------------------------------------ PUNCH ATTACK CYCLE ------------------------------------------------------------------------------------------ **/ //if the a key is pressed while idling or running, cycle between punch, kick and rapid punch if (current_move != moves.DASH_ATTACK && current_move != moves.CROUCH && !grabbing_edge) { if (current_move == moves.IDLE || (current_move == moves.RUN && !right_key->down && !left_key->down)) { if (a_key->pressed) { if (moves.name == CAPTAIN_FALCON) { if ((punch_cycle == moves.KICK || punch_cycle == moves.RAPID_PUNCH) && punch_timer <= PUNCH_CYCLE_TIME) { //change move to rapid punch update_move(moves.RAPID_PUNCH, 20, false, true); punch_cycle = moves.RAPID_PUNCH; base_parent->dealt_damage = false; }else if (punch_cycle == moves.PUNCH && punch_timer <= PUNCH_CYCLE_TIME) { //change move to kick update_move(moves.KICK, 15, false, true); punch_cycle = moves.KICK; base_parent->dealt_damage = false; }else { //change move to punch update_move(moves.PUNCH, 10, false, true); punch_cycle = moves.PUNCH; base_parent->dealt_damage = false; } }else if (moves.name == THOR) { if ((punch_cycle == moves.HAMMER_PUNCH_UP || punch_cycle == moves.HAMMER_COMBO_PUNCH) && punch_timer <= PUNCH_CYCLE_TIME) { //change move to hammer combo punch update_move(moves.HAMMER_COMBO_PUNCH, 30, false, true); punch_cycle = moves.HAMMER_PUNCH; base_parent->dealt_damage = false; }else if (punch_cycle == moves.HAMMER_PUNCH && punch_timer <= PUNCH_CYCLE_TIME) { //change move to hammer punch up update_move(moves.HAMMER_PUNCH_UP, 30, false, true); punch_cycle = moves.HAMMER_PUNCH_UP; base_parent->dealt_damage = false; }else { //change move to hammer punch update_move(moves.HAMMER_PUNCH, 20, false, true); punch_cycle = moves.HAMMER_PUNCH; base_parent->dealt_damage = false; } } //restrict movement input and reset punch timer punch_timer = 0; restrict_input_x = true; restrict_input_y = true; punching = true; } } } //increment punch_timer and allow movement input after a move in the punch cycle has been performed if (punching && !lock_move_update) { restrict_input_x = false; restrict_input_y = false; punching = false; update_move(moves.IDLE, 5, true); }else { ++punch_timer; if (punch_timer >= PUNCH_CYCLE_TIME) { punch_timer = 0; punch_cycle = moves.IDLE; } } /** ------------------------------------------------------------------------------------------ RUN + DASH ATTACK ------------------------------------------------------------------------------------------ **/ //if the dash attack is not on cooldown then perform a dash attack when the a is pressed if (!dashing) { ++dash_cooldown_timer; } if (current_move == moves.RUN && dash_cooldown_timer >= DASH_COOLDOWN && !grabbing_edge) { if (a_key->pressed) { //apply force depending on flip direction if (flip == SDL_RendererFlip::SDL_FLIP_NONE) { force_x += 10; }else { force_x -= 10; } //update movement and restrict movement input update_move(moves.DASH_ATTACK, moves.DASH_ATTACK_FPS, false, true); restrict_input_x = true; restrict_input_y = true; base_parent->dealt_damage = false; dashing = true; dash_cooldown_timer = 0; } } //if dashing and slowed down then end dash and allow movement input if (dashing && speed_x <= 2 && speed_x >= -2 && !lock_move_update) { restrict_input_x = false; restrict_input_y = false; dashing = false; animator->paused = false; update_move(moves.IDLE, 5, true); } /** ------------------------------------------------------------------------------------------ CROUCH SLIDE ATTACK ------------------------------------------------------------------------------------------ **/ //if the down key is down then change the move to crouch if (floor_collided) { if (down_key->down) { if (!restrict_input_y && current_move != moves.SLIDE_ATTACK) { update_move(moves.CROUCH, 5, false); } } } //if the slide attack is not on cooldown then perform a slide attack when the a is pressed if (!sliding) { ++sliding_cooldown_timer; } if (current_move == moves.CROUCH && sliding_cooldown_timer >= SLIDE_COOLDOWN && !grabbing_edge) { if (a_key->pressed && down_key->down) { //apply force depending on flip direction if (flip == SDL_RendererFlip::SDL_FLIP_NONE) { force_x += 8; }else { force_x -= 8; } //update movement and restrict movement input update_move(moves.SLIDE_ATTACK, moves.SLIDE_ATTACK_FPS, false, true); restrict_input_x = true; restrict_input_y = true; sliding = true; base_parent->dealt_damage = false; sliding_cooldown_timer = 0; speed_x += force_x; } } //if sliding and slowed down then end slide and allow movement input if (sliding && speed_x <= 1 && speed_x >= -1 && !lock_move_update) { restrict_input_x = false; restrict_input_y = false; sliding = false; animator->paused = false; update_move(moves.IDLE, 5, true); } /** ------------------------------------------------------------------------------------------ DOWN AIR KICK ------------------------------------------------------------------------------------------ **/ if (!floor_collided && down_key->down && a_key->pressed && !restrict_input_y && !grabbing_edge) { if (moves.name != CAPTAIN_FALCON || !double_jump) { if (moves.name == CAPTAIN_FALCON) { update_move(moves.AIR_DOWN_KICK, 15, false, true); }else if (moves.name == THOR) { update_move(moves.HAMMER_SLAM_DOWN, 10, false, true); } restrict_input_x = true; restrict_input_y = true; down_air_kick = true; base_parent->dealt_damage = false; } } if (down_air_kick && !lock_move_update && moves.name == CAPTAIN_FALCON) { update_move(moves.JUMP, 10, false); double_jump = false; restrict_input_x = false; restrict_input_y = false; down_air_kick = false; } if (down_hammer_slam && !lock_move_update) { update_move(moves.LAND, 10, false); double_jump = false; restrict_input_x = false; restrict_input_y = false; down_hammer_slam = false; } /** ------------------------------------------------------------------------------------------ RIGHT AIR KNEE ------------------------------------------------------------------------------------------ **/ if (!floor_collided && a_key->pressed && !double_jump && !restrict_input_y && !grabbing_edge && ((flip == SDL_RendererFlip::SDL_FLIP_NONE && right_key->down) || (flip == SDL_RendererFlip::SDL_FLIP_HORIZONTAL && left_key->down))) { update_move(moves.AIR_KNEE, 15, false, true); restrict_input_x = true; restrict_input_y = true; right_air_knee = true; base_parent->dealt_damage = false; } if (right_air_knee && !lock_move_update) { update_move(moves.JUMP, 10, false); double_jump = false; restrict_input_x = false; restrict_input_y = false; right_air_knee = false; } /** ------------------------------------------------------------------------------------------ AIR SOMERSAULT ------------------------------------------------------------------------------------------ **/ if (!floor_collided && up_key->down && !down_key->pressed && a_key->pressed && !grabbing_edge && !restrict_input_y && !air_somersault) { update_move(moves.AIR_SOMERSAULT, 15, false, true); restrict_input_x = true; restrict_input_y = true; air_somersault = true; base_parent->dealt_damage = false; rotation = 0; } if (air_somersault && !lock_move_update) { update_move(moves.JUMP, 10, false); restrict_input_x = false; restrict_input_y = false; air_somersault = false; } /** ------------------------------------------------------------------------------------------ RIGHT AIR KICK ------------------------------------------------------------------------------------------ **/ if (!floor_collided && a_key->pressed && !double_jump && !restrict_input_y && !right_key->down && !left_key->down && !up_key->down && !grabbing_edge) { update_move(moves.AIR_KICK, moves.AIR_KICK_FPS, false); restrict_input_x = true; restrict_input_y = true; right_air_kick = true; base_parent->dealt_damage = false; } if (right_air_kick) { if (animator->paused || current_move != moves.AIR_KICK) { update_move(moves.JUMP, 10, false); double_jump = false; restrict_input_x = false; restrict_input_y = false; right_air_kick = false; } } /** ------------------------------------------------------------------------------------------ APPLY VALUES ------------------------------------------------------------------------------------------ **/ //apply force friction to force_x force_x = force_x * FORCE_FRICTION; //apply speedx and gravity to the position pos.x += speed_x; pos.y += gravity; //apply force_x to the position pos.x += force_x; //if the animation is locked and has looped once then unlock it if ((lock_move_update || current_move == moves.HIT) && animator->looped >= 1) { lock_move_update = false; if (current_move == moves.HIT) { if (!floor_collided) { update_move(moves.JUMP, 10, false); }else { update_move(moves.IDLE, 5, true); } //restrict_input_x = false; //restrict_input_y = false; } } //update the animator animator->update(); }