Search in sources :

Example 1 with HorizontalCollisionEvent

use of org.terasology.logic.characters.events.HorizontalCollisionEvent in project Terasology by MovingBlocks.

the class KinematicCharacterMover method walk.

private void walk(final CharacterMovementComponent movementComp, final CharacterStateEvent state, CharacterMoveInputEvent input, EntityRef entity) {
    Vector3f desiredVelocity = new Vector3f(input.getMovementDirection());
    float lengthSquared = desiredVelocity.lengthSquared();
    // (Desired velocity < 1 is allowed, as the character may wish to walk/crawl/otherwise move slowly)
    if (lengthSquared > 1) {
        desiredVelocity.normalize();
    }
    desiredVelocity.scale(movementComp.speedMultiplier);
    float maxSpeed = getMaxSpeed(entity, movementComp);
    if (input.isRunning()) {
        maxSpeed *= movementComp.runFactor;
    }
    // As we can't use it, remove the y component of desired movement while maintaining speed.
    if (movementComp.grounded && desiredVelocity.y != 0) {
        float speed = desiredVelocity.length();
        desiredVelocity.y = 0;
        if (desiredVelocity.x != 0 || desiredVelocity.z != 0) {
            desiredVelocity.normalize();
            desiredVelocity.scale(speed);
        }
    }
    desiredVelocity.scale(maxSpeed);
    if (movementComp.mode == MovementMode.CLIMBING) {
        climb(state, input, desiredVelocity);
    }
    // Modify velocity towards desired, up to the maximum rate determined by friction
    Vector3f velocityDiff = new Vector3f(desiredVelocity);
    velocityDiff.sub(state.getVelocity());
    velocityDiff.scale(Math.min(movementComp.mode.scaleInertia * input.getDelta(), 1.0f));
    Vector3f endVelocity = new Vector3f(state.getVelocity());
    endVelocity.x += velocityDiff.x;
    endVelocity.z += velocityDiff.z;
    if (movementComp.mode.scaleGravity == 0) {
        // apply the velocity without gravity
        endVelocity.y += velocityDiff.y;
    } else if (movementComp.mode.applyInertiaToVertical) {
        endVelocity.y += Math.max(-TERMINAL_VELOCITY, velocityDiff.y - (GRAVITY * movementComp.mode.scaleGravity) * input.getDelta());
    } else {
        endVelocity.y = Math.max(-TERMINAL_VELOCITY, state.getVelocity().y - (GRAVITY * movementComp.mode.scaleGravity) * input.getDelta());
    }
    Vector3f moveDelta = new Vector3f(endVelocity);
    moveDelta.scale(input.getDelta());
    CharacterCollider collider = movementComp.mode.useCollision ? physics.getCharacterCollider(entity) : null;
    MoveResult moveResult = move(state.getPosition(), moveDelta, (state.getMode() != MovementMode.CLIMBING && state.isGrounded() && movementComp.mode.canBeGrounded) ? movementComp.stepHeight : 0, movementComp.slopeFactor, collider);
    Vector3f distanceMoved = new Vector3f(moveResult.getFinalPosition());
    distanceMoved.sub(state.getPosition());
    state.getPosition().set(moveResult.getFinalPosition());
    if (input.isFirstRun() && distanceMoved.length() > 0) {
        entity.send(new MovedEvent(distanceMoved, state.getPosition()));
    }
    // Upon hitting solid ground, reset the number of jumps back to the maximum value.
    if (state.isGrounded()) {
        movementComp.numberOfJumpsLeft = movementComp.numberOfJumpsMax;
    }
    if (moveResult.isBottomHit()) {
        if (!state.isGrounded() && movementComp.mode.canBeGrounded) {
            if (input.isFirstRun()) {
                Vector3f landVelocity = new Vector3f(state.getVelocity());
                landVelocity.y += (distanceMoved.y / moveDelta.y) * (endVelocity.y - state.getVelocity().y);
                logger.debug("Landed at " + landVelocity);
                entity.send(new VerticalCollisionEvent(state.getPosition(), landVelocity));
            }
            state.setGrounded(true);
            movementComp.numberOfJumpsLeft = movementComp.numberOfJumpsMax;
        }
        endVelocity.y = 0;
        // Jumping is only possible, if the entity is standing on ground
        if (input.isJumpRequested()) {
            state.setGrounded(false);
            // Send event to allow for other systems to modify the jump force.
            AffectJumpForceEvent affectJumpForceEvent = new AffectJumpForceEvent(movementComp.jumpSpeed);
            entity.send(affectJumpForceEvent);
            endVelocity.y += affectJumpForceEvent.getResultValue();
            if (input.isFirstRun()) {
                entity.send(new JumpEvent());
            }
            // Send event to allow for other systems to modify the max number of jumps.
            AffectMultiJumpEvent affectMultiJumpEvent = new AffectMultiJumpEvent(movementComp.baseNumberOfJumpsMax);
            entity.send(affectMultiJumpEvent);
            movementComp.numberOfJumpsMax = (int) affectMultiJumpEvent.getResultValue();
            movementComp.numberOfJumpsLeft--;
        }
    } else {
        if (moveResult.isTopHit() && endVelocity.y > 0) {
            if (input.isFirstRun()) {
                Vector3f hitVelocity = new Vector3f(state.getVelocity());
                hitVelocity.y += (distanceMoved.y / moveDelta.y) * (endVelocity.y - state.getVelocity().y);
                logger.debug("Hit at " + hitVelocity);
                entity.send(new VerticalCollisionEvent(state.getPosition(), hitVelocity));
            }
            endVelocity.y = -0.0f * endVelocity.y;
        }
        // Jump again in mid-air only if a jump was requested and there are jumps remaining.
        if (input.isJumpRequested() && movementComp.numberOfJumpsLeft > 0) {
            state.setGrounded(false);
            // Send event to allow for other systems to modify the jump force.
            AffectJumpForceEvent affectJumpForceEvent = new AffectJumpForceEvent(movementComp.jumpSpeed);
            entity.send(affectJumpForceEvent);
            endVelocity.y += affectJumpForceEvent.getResultValue();
            if (input.isFirstRun()) {
                entity.send(new JumpEvent());
            }
            // Send event to allow for other systems to modify the max number of jumps.
            AffectMultiJumpEvent affectMultiJumpEvent = new AffectMultiJumpEvent(movementComp.baseNumberOfJumpsMax);
            entity.send(affectMultiJumpEvent);
            movementComp.numberOfJumpsMax = (int) affectMultiJumpEvent.getResultValue();
            movementComp.numberOfJumpsLeft--;
        }
        state.setGrounded(false);
    }
    if (input.isFirstRun() && moveResult.isHorizontalHit()) {
        Vector3f hitVelocity = new Vector3f(state.getVelocity());
        hitVelocity.x += (distanceMoved.x / moveDelta.x) * (endVelocity.x - state.getVelocity().x);
        hitVelocity.z += (distanceMoved.z / moveDelta.z) * (endVelocity.z - state.getVelocity().z);
        logger.debug("Hit at " + hitVelocity);
        entity.send(new HorizontalCollisionEvent(state.getPosition(), hitVelocity));
    }
    state.getVelocity().set(endVelocity);
    if (state.isGrounded() || movementComp.mode == MovementMode.SWIMMING || movementComp.mode == MovementMode.DIVING) {
        state.setFootstepDelta(state.getFootstepDelta() + distanceMoved.length() / movementComp.distanceBetweenFootsteps);
        if (state.getFootstepDelta() > 1) {
            state.setFootstepDelta(state.getFootstepDelta() - 1);
            if (input.isFirstRun()) {
                switch(movementComp.mode) {
                    case CROUCHING:
                    case WALKING:
                        entity.send(new FootstepEvent());
                        break;
                    case DIVING:
                    case SWIMMING:
                        entity.send(new SwimStrokeEvent(worldProvider.getBlock(state.getPosition())));
                        break;
                    case CLIMBING:
                    case FLYING:
                    case GHOSTING:
                    case NONE:
                        break;
                }
            }
        }
    }
}
Also used : SwimStrokeEvent(org.terasology.logic.characters.events.SwimStrokeEvent) CharacterCollider(org.terasology.physics.engine.CharacterCollider) Vector3f(org.terasology.math.geom.Vector3f) JumpEvent(org.terasology.logic.characters.events.JumpEvent) FootstepEvent(org.terasology.logic.characters.events.FootstepEvent) VerticalCollisionEvent(org.terasology.logic.characters.events.VerticalCollisionEvent) HorizontalCollisionEvent(org.terasology.logic.characters.events.HorizontalCollisionEvent) MovedEvent(org.terasology.physics.events.MovedEvent)

Aggregations

FootstepEvent (org.terasology.logic.characters.events.FootstepEvent)1 HorizontalCollisionEvent (org.terasology.logic.characters.events.HorizontalCollisionEvent)1 JumpEvent (org.terasology.logic.characters.events.JumpEvent)1 SwimStrokeEvent (org.terasology.logic.characters.events.SwimStrokeEvent)1 VerticalCollisionEvent (org.terasology.logic.characters.events.VerticalCollisionEvent)1 Vector3f (org.terasology.math.geom.Vector3f)1 CharacterCollider (org.terasology.physics.engine.CharacterCollider)1 MovedEvent (org.terasology.physics.events.MovedEvent)1