예제 #1
0
VerticalFacing Player::vertical_facing() const
{
    if (is_on_ground() && intended_vertical_facing_ == VerticalFacing::DOWN) {
        return VerticalFacing::HORIZONTAL;
    } else {
        return intended_vertical_facing_;
    }
}
예제 #2
0
void Player::startJump()
{
    is_interacting_ = false;
    is_jump_active_ = true;
    if (is_on_ground()) {
        velocity_.y = -kJumpSpeed;
    }
}
예제 #3
0
void Player::startMovingRight()
{
    if (is_on_ground() && acceleration_x_direction_ == 0) {
        walking_animation_.reset();
    }
    horizontal_facing_ = HorizontalFacing::RIGHT;
    acceleration_x_direction_ = 1;
    is_interacting_ = false;
}
예제 #4
0
MotionType Player::getMotionType() const
{
    MotionType motion;
    if (is_interacting_) {
        motion = MotionType::INTERACTING;
    } else if (is_on_ground()) {
        motion = acceleration_x_direction_ == 0
            ? MotionType::STANDING
            : MotionType::WALKING;
    } else {
        motion = velocity_.y < 0.0
            ? MotionType::JUMPING
            : MotionType::FALLING;
    }
    return motion;
}
예제 #5
0
body_part Creature::select_body_part(Creature *source, int hit_roll) const
{
    // Get size difference (-1,0,1);
    int szdif = source->get_size() - get_size();
    if(szdif < -1) {
        szdif = -1;
    } else if (szdif > 1) {
        szdif = 1;
    }

    add_msg( m_debug, "hit roll = %d", hit_roll);
    add_msg( m_debug, "source size = %d", source->get_size() );
    add_msg( m_debug, "target size = %d", get_size() );
    add_msg( m_debug, "difference = %d", szdif );

    std::map<body_part, double> hit_weights = default_hit_weights[szdif];

    // If the target is on the ground, even small/tiny creatures may target eyes/head. Also increases chances of larger creatures.
    // Any hit modifiers to locations should go here. (Tags, attack style, etc)
    if(is_on_ground()) {
        hit_weights[bp_eyes] += 1;
        hit_weights[bp_head] += 5;
    }

    //Adjust based on hit roll: Eyes, Head & Torso get higher, while Arms and Legs get lower.
    //This should eventually be replaced with targeted attacks and this being miss chances.
    // pow() is unstable at 0, so don't apply any changes.
    if( hit_roll != 0 ) {
        hit_weights[bp_eyes] *= std::pow(hit_roll, 1.15);
        hit_weights[bp_head] *= std::pow(hit_roll, 1.35);
        hit_weights[bp_torso] *= std::pow(hit_roll, 1);
        hit_weights[bp_arm_l] *= std::pow(hit_roll, 0.95);
        hit_weights[bp_arm_r] *= std::pow(hit_roll, 0.95);
        hit_weights[bp_leg_l] *= std::pow(hit_roll, 0.975);
        hit_weights[bp_leg_r] *= std::pow(hit_roll, 0.975);
    }

    // Debug for seeing weights.
    add_msg( m_debug, "eyes = %f", hit_weights.at( bp_eyes ) );
    add_msg( m_debug, "head = %f", hit_weights.at( bp_head ) );
    add_msg( m_debug, "torso = %f", hit_weights.at( bp_torso ) );
    add_msg( m_debug, "arm_l = %f", hit_weights.at( bp_arm_l ) );
    add_msg( m_debug, "arm_r = %f", hit_weights.at( bp_arm_r ) );
    add_msg( m_debug, "leg_l = %f", hit_weights.at( bp_leg_l ) );
    add_msg( m_debug, "leg_r = %f", hit_weights.at( bp_leg_r ) );

    double totalWeight = 0;
    for( const auto &hit_weight : hit_weights ) {
        totalWeight += hit_weight.second;
    }

    double roll = rng_float(0, totalWeight);
    body_part selected_part = bp_torso;

    for( const auto &hit_candidate : hit_weights) {
        roll -= hit_candidate.second;
        if(roll <= 0) {
            selected_part = hit_candidate.first;
            break;
        }
    }

    add_msg( m_debug, "selected part: %s", body_part_name(selected_part).c_str() );

    return selected_part;
}
예제 #6
0
body_part Creature::select_body_part(Creature *source, int hit_roll)
{
    // Get size difference (-1,0,1);
    int szdif = source->get_size() - get_size();
    if(szdif < -1) {
        szdif = -1;
    } else if (szdif > 1) {
        szdif = 1;
    }

    if(g->debugmon) {
        g->add_msg("source size = %d", source->get_size());
        g->add_msg("target size = %d", get_size());
        g->add_msg("difference = %d", szdif);
    }

    std::map<body_part, double> hit_weights = default_hit_weights[szdif];
    std::map<body_part, double>::iterator iter;

    // If the target is on the ground, even small/tiny creatures may target eyes/head. Also increases chances of larger creatures.
    // Any hit modifiers to locations should go here. (Tags, attack style, etc)
    if(is_on_ground()) {
        hit_weights[bp_eyes] += 10;
        hit_weights[bp_head] += 20;
    }

    //Adjust based on hit roll: Eyes, Head & Torso get higher, while Arms and Legs get lower.
    //This should eventually be replaced with targeted attacks and this being miss chances.
    hit_weights[bp_eyes] = floor(hit_weights[bp_eyes] * pow(hit_roll, 1.15) * 10);
    hit_weights[bp_head] = floor(hit_weights[bp_head] * pow(hit_roll, 1.15) * 10);
    hit_weights[bp_torso] = floor(hit_weights[bp_torso] * pow(hit_roll, 1) * 10);
    hit_weights[bp_arms] = floor(hit_weights[bp_arms] * pow(hit_roll, 0.95) * 10);
    hit_weights[bp_legs] = floor(hit_weights[bp_legs] * pow(hit_roll, 0.975) * 10);


    // Debug for seeing weights.
    if(g->debugmon) {
        g->add_msg("eyes = %f", hit_weights.at(bp_eyes));
        g->add_msg("head = %f", hit_weights.at(bp_head));
        g->add_msg("torso = %f", hit_weights.at(bp_torso));
        g->add_msg("arms = %f", hit_weights.at(bp_arms));
        g->add_msg("legs = %f", hit_weights.at(bp_legs));
    }

    double totalWeight = 0;
    std::set<weight_pair, weight_compare> adjusted_weights;
    for(iter = hit_weights.begin(); iter != hit_weights.end(); ++iter) {
        totalWeight += iter->second;
        adjusted_weights.insert(*iter);
    }

    double roll = rng_float(1, totalWeight);
    body_part selected_part = bp_torso;

    std::set<weight_pair, weight_compare>::iterator adj_iter;
    for(adj_iter = adjusted_weights.begin(); adj_iter != adjusted_weights.end(); ++adj_iter) {
        roll -= adj_iter->second;
        if(roll <= 0) {
            selected_part = adj_iter->first;
            break;
        }
    }

    return selected_part;
}
예제 #7
0
파일: Player.cpp 프로젝트: ikkentim/chr2r
Player::AnimationState Player::get_animation_state(int &frames) {
    frames = 1;

    if (is_ducking()) { /* Is ducking. */
        if (velocity_.x < 0) { /* Is moving left. */
            return DUCK_LEFT;
        }
        if (velocity_.x > 0) { /* Is moving right. */
            return DUCK_RIGHT;
        }
        return isLastMovementLeft_ ? DUCK_LEFT : DUCK_RIGHT;
    }
    else if (state() == GameScene::PLAYER_DEAD){
        return DEAD_;
    }
    else if (is_splashing()){ /*SPLASH ATTACK*/
        frames = 2;
        return SPLASHING_;
    }
    else if (velocity_.is_zero()){ /* Not moving at all. */
        return isLastMovementLeft_ ? IDLE_LEFT : IDLE_RIGHT;
    }
    else if (is_on_ground()) {/* Is on ground. */

        if (velocity_.x > 0) { /* Is moving right. */
            if (keys_ & KEY_LEFT) {
                return SLIDE_RIGHT;
            }
            frames = 3;
            return RUN_RIGHT;
        }
        if (velocity_.x < 0) { /* Is moving left. */
            if (keys_ & KEY_RIGHT) {
                return SLIDE_LEFT;
            }
            frames = 3;
            return RUN_LEFT;
        }
        return isLastMovementLeft_ ? IDLE_LEFT : IDLE_RIGHT;
    }
    else {
        if (velocity_.y < -0.1f) { /* Jumping. */
            if (velocity_.x > 0) { /* Is moving right or straight up. */
                return JUMP_RIGHT;
            }
            if (velocity_.x < 0) { /* Is moving left. */
                return JUMP_LEFT;
            }
            return isLastMovementLeft_ ? JUMP_LEFT : JUMP_RIGHT;
        }
        else { /* Falling */
            if (velocity_.x > 0) { /* Is moving right or straight up. */
                return FALL_RIGHT;
            }
            if (velocity_.x < 0) { /* Is moving left. */
                return FALL_LEFT;
            }
            return isLastMovementLeft_ ? FALL_LEFT : FALL_RIGHT;
        }
    }
}
예제 #8
0
void Player::updateX(const std::chrono::milliseconds elapsed_time,
                     const Map& map,
                     ParticleTools&)
{
    // Update velocity
    units::Acceleration acceleration_x{0.0};
    if (acceleration_x_direction_ < 0) {
        acceleration_x = is_on_ground()
            ? -kWalkingAcceleration
            : -kAirAcceleration;
    } else if (acceleration_x_direction_ > 0) {
        acceleration_x = is_on_ground()
            ? kWalkingAcceleration
            : kAirAcceleration;
    }

    velocity_.x += acceleration_x * elapsed_time.count();

    if (acceleration_x_direction_ < 0) {
        velocity_.x = std::max(velocity_.x, -kMaxSpeedX);
    } else if (acceleration_x_direction_ > 0) {
        velocity_.x = std::min(velocity_.x, kMaxSpeedX);
    } else if (is_on_ground()) {
        velocity_.x = velocity_.x > 0.0
            ? std::max(0.0, velocity_.x - kFriction * elapsed_time.count())
            : std::min(0.0, velocity_.x + kFriction * elapsed_time.count());
    }
    // Calculate delta
    const units::Game delta = velocity_.x * elapsed_time.count();

    if (delta > 0.0) {
        // Check collision in the direction of delta
        CollisionInfo info = getWallCollisionInfo(map, rightCollision(delta));
        // React to collision
        if (info.collided) {
            pos_.x = units::tileToGame(info.col) - kCollisionX.getRight();
            velocity_.x = 0.0;
        } else {
            pos_.x += delta;
        }
        // Check collision in the direction opposite to delta
        info = getWallCollisionInfo(map, leftCollision(0));
        if (info.collided) {
            pos_.x = units::tileToGame(info.col) + kCollisionX.getRight();
        }
    } else {
        // Check collision in the direction of delta
        CollisionInfo info = getWallCollisionInfo(map, leftCollision(delta));
        // React to collision
        if (info.collided) {
            pos_.x = units::tileToGame(info.col) + kCollisionX.getRight();
            velocity_.x = 0.0;
        } else {
            pos_.x += delta;
        }
        // Check collision in the direction opposite to delta
        info = getWallCollisionInfo(map, rightCollision(0));
        if (info.collided) {
            pos_.x = units::tileToGame(info.col) - kCollisionX.getRight();
        }
    }
}
예제 #9
0
void Player::lookDown()
{
    if (intended_vertical_facing_ == VerticalFacing::DOWN) return;
    intended_vertical_facing_ = VerticalFacing::DOWN;
    is_interacting_ = is_on_ground();
}
예제 #10
0
body_part Creature::select_body_part(Creature *source, int hit_roll)
{
    // Get size difference (-1,0,1);
    int szdif = source->get_size() - get_size();
    if(szdif < -1) {
        szdif = -1;
    } else if (szdif > 1) {
        szdif = 1;
    }

    add_msg( m_debug, "source size = %d", source->get_size() );
    add_msg( m_debug, "target size = %d", get_size() );
    add_msg( m_debug, "difference = %d", szdif );

    std::map<body_part, double> hit_weights = default_hit_weights[szdif];
    std::map<body_part, double>::iterator iter;

    // If the target is on the ground, even small/tiny creatures may target eyes/head. Also increases chances of larger creatures.
    // Any hit modifiers to locations should go here. (Tags, attack style, etc)
    if(is_on_ground()) {
        hit_weights[bp_eyes] += 10;
        hit_weights[bp_head] += 20;
    }

    //Adjust based on hit roll: Eyes, Head & Torso get higher, while Arms and Legs get lower.
    //This should eventually be replaced with targeted attacks and this being miss chances.
    hit_weights[bp_eyes] = floor(hit_weights[bp_eyes] * std::pow(hit_roll, 1.15) * 10);
    hit_weights[bp_head] = floor(hit_weights[bp_head] * std::pow(hit_roll, 1.15) * 10);
    hit_weights[bp_torso] = floor(hit_weights[bp_torso] * std::pow(hit_roll, 1) * 10);
    hit_weights[bp_arm_l] = floor(hit_weights[bp_arm_l] * std::pow(hit_roll, 0.95) * 10);
    hit_weights[bp_arm_r] = floor(hit_weights[bp_arm_r] * std::pow(hit_roll, 0.95) * 10);
    hit_weights[bp_leg_l] = floor(hit_weights[bp_leg_l] * std::pow(hit_roll, 0.975) * 10);
    hit_weights[bp_leg_r] = floor(hit_weights[bp_leg_r] * std::pow(hit_roll, 0.975) * 10);


    // Debug for seeing weights.
    add_msg( m_debug, "eyes = %f", hit_weights.at( bp_eyes ) );
    add_msg( m_debug, "head = %f", hit_weights.at( bp_head ) );
    add_msg( m_debug, "torso = %f", hit_weights.at( bp_torso ) );
    add_msg( m_debug, "arm_l = %f", hit_weights.at( bp_arm_l ) );
    add_msg( m_debug, "arm_r = %f", hit_weights.at( bp_arm_r ) );
    add_msg( m_debug, "leg_l = %f", hit_weights.at( bp_leg_l ) );
    add_msg( m_debug, "leg_r = %f", hit_weights.at( bp_leg_r ) );

    double totalWeight = 0;
    std::set<std::pair<body_part, double>, weight_compare> adjusted_weights;
    for(iter = hit_weights.begin(); iter != hit_weights.end(); ++iter) {
        totalWeight += iter->second;
        adjusted_weights.insert(*iter);
    }

    body_part selected_part = bp_torso;

    // Blood thirsty monsters can discard body part and go to more damaged
    int part_rolls = 1;
    int repick_chance = 50;
    if (source->has_flag(MF_BLOODTHIRSTY)) {
        part_rolls += 2;
        if (is_player() && g->u.has_trait("ANIMALEMPATH")) {
            part_rolls -= 1;
            repick_chance -= 10;
        }
        if (is_player() && g->u.has_trait("ANIMALDISCORD")) {
            part_rolls += 1;
            repick_chance += 10;
        }
    }
    body_part last_part = selected_part;
    for(int r = 0; r < part_rolls; ++r) {
        double roll = rng_float(1, totalWeight);
        std::set<std::pair<body_part, double>, weight_compare>::iterator adj_iter;
        for(adj_iter = adjusted_weights.begin(); adj_iter != adjusted_weights.end(); ++adj_iter) {
            roll -= adj_iter->second;
            if(roll <= 0) {
                selected_part = adj_iter->first;
                break;
            }
        }

        if (r != 0) {
            hp_part hpart_cur = bodypart_to_hp_part(selected_part);
            hp_part hpart_lst = bodypart_to_hp_part(last_part);
            double ratio_cur = get_hp(hpart_cur) / float(get_hp_max(hpart_cur));
            double ratio_lst = get_hp(hpart_lst) / float(get_hp_max(hpart_lst));
            body_part cur_pick_part = selected_part;
            if(ratio_cur > ratio_lst && repick_chance >= rng(1,100))
                selected_part = last_part;
            add_msg( m_debug, "picked %s from %s(%.2f)/%s(%.2f)",
                        body_part_name(selected_part).c_str(), 
                        body_part_name(cur_pick_part).c_str(), ratio_cur,
                        body_part_name(last_part).c_str(), ratio_lst);
        }
        last_part = selected_part;
    }

    return selected_part;
}