private void playMovementSound() { if (_godMode) return; if ((MathHelper.fastAbs(_velocity.x) > 0.01 || MathHelper.fastAbs(_velocity.z) > 0.01) && _touchingGround) { if (_currentFootstepSound == null) { Vector3d playerDirection = directionOfReferencePoint(); _currentFootstepSound = _footstepSounds[ MathHelper.fastAbs(_parent.getWorldProvider().getRandom().randomInt()) % 5]; _currentFootstepSound.playAsSoundEffect( 0.7f + (float) MathHelper.fastAbs(_parent.getWorldProvider().getRandom().randomDouble()) * 0.3f, 0.2f + (float) MathHelper.fastAbs(_parent.getWorldProvider().getRandom().randomDouble()) * 0.2f, false, (float) playerDirection.x, (float) playerDirection.y, (float) playerDirection.z); } else { long timeDiff = Terasology.getInstance().getTime() - _lastFootStepSoundPlayed; if (!_currentFootstepSound.isPlaying() && timeDiff > 400 / (_activeWalkingSpeed / _walkingSpeed)) { _lastFootStepSoundPlayed = Terasology.getInstance().getTime(); _currentFootstepSound = null; } } } }
/** Updates the status if the entity is currently swimming (in water). */ private void updateSwimStatus() { ArrayList<BlockPosition> blockPositions = gatherAdjacentBlockPositions(getPosition()); boolean swimming = false, headUnderWater = false; for (int i = 0; i < blockPositions.size(); i++) { BlockPosition p = blockPositions.get(i); byte blockType = _parent.getWorldProvider().getBlockAtPosition(new Vector3d(p.x, p.y, p.z)); AABB blockAABB = Block.AABBForBlockAt(p.x, p.y, p.z); if (BlockManager.getInstance().getBlock(blockType).isLiquid() && getAABB().overlaps(blockAABB)) { swimming = true; } Vector3d eyePos = calcEyePosition(); eyePos.y += 0.25; if (BlockManager.getInstance().getBlock(blockType).isLiquid() && blockAABB.contains(eyePos)) { headUnderWater = true; } } _headUnderWater = headUnderWater; _isSwimming = swimming; }
/** * Checks for blocks around the entity. * * @param origin The original position of the entity * @return True if the entity is colliding horizontally */ private boolean horizontalHitTest(Vector3d origin) { boolean result = false; ArrayList<BlockPosition> blockPositions = gatherAdjacentBlockPositions(origin); // Check each block position for collision for (int i = 0; i < blockPositions.size(); i++) { BlockPosition p = blockPositions.get(i); byte blockType = _parent.getWorldProvider().getBlockAtPosition(new Vector3d(p.x, p.y, p.z)); AABB blockAABB = Block.AABBForBlockAt(p.x, p.y, p.z); if (!BlockManager.getInstance().getBlock(blockType).isPenetrable()) { if (getAABB().overlaps(blockAABB)) { result = true; // Calculate the direction from the origin to the current position Vector3d direction = new Vector3d(getPosition().x, 0f, getPosition().z); direction.x -= origin.x; direction.z -= origin.z; // Calculate the point of intersection on the block's AABB Vector3d blockPoi = blockAABB.closestPointOnAABBToPoint(origin); Vector3d entityPoi = generateAABBForPosition(origin).closestPointOnAABBToPoint(blockPoi); Vector3d planeNormal = blockAABB.normalForPlaneClosestToOrigin(blockPoi, origin, true, false, true); // Find a vector parallel to the surface normal Vector3d slideVector = new Vector3d(planeNormal.z, 0, -planeNormal.x); Vector3d pushBack = new Vector3d(); pushBack.sub(blockPoi, entityPoi); // Calculate the intensity of the diversion alongside the block double length = slideVector.dot(direction); Vector3d newPosition = new Vector3d(); newPosition.z = origin.z + pushBack.z * 0.2 + length * slideVector.z; newPosition.x = origin.x + pushBack.x * 0.2 + length * slideVector.x; newPosition.y = origin.y; // Update the position getPosition().set(newPosition); } } } return result; }
/** * Checks for blocks below and above the entity. * * @param origin The origin position of the entity * @return True if a vertical collision was detected */ private boolean verticalHitTest(Vector3d origin) { ArrayList<BlockPosition> blockPositions = gatherAdjacentBlockPositions(origin); for (int i = 0; i < blockPositions.size(); i++) { BlockPosition p = blockPositions.get(i); byte blockType1 = _parent.getWorldProvider().getBlockAtPosition(new Vector3d(p.x, p.y, p.z)); AABB entityAABB = getAABB(); if (BlockManager.getInstance().getBlock(blockType1).isPenetrable() || !entityAABB.overlaps(Block.AABBForBlockAt(p.x, p.y, p.z))) continue; double direction = origin.y - getPosition().y; if (direction >= 0) getPosition().y = p.y + 0.50001f + entityAABB.getDimensions().y; else getPosition().y = p.y - 0.50001f - entityAABB.getDimensions().y; return true; } return false; }
public Vector3d directionOfReferencePoint() { Vector3d result = new Vector3d(); result.sub(_parent.getWorldProvider().getRenderingReferencePoint(), getPosition()); return result; }
/** Updates the position of the entity. */ protected void updatePosition() { // Save the previous position before changing any of the values Vector3d oldPosition = new Vector3d(getPosition()); double friction = (Double) ConfigurationManager.getInstance().getConfig().get("Player.friction"); /* * Slowdown the speed of the entity each time this method is called. */ if (MathHelper.fastAbs(_velocity.y) > 0f) { _velocity.y += -1f * _velocity.y * friction; } if (MathHelper.fastAbs(_velocity.x) > 0f) { _velocity.x += -1f * _velocity.x * friction; } if (MathHelper.fastAbs(_velocity.z) > 0f) { _velocity.z += -1f * _velocity.z * friction; } /* * Apply friction. */ if (MathHelper.fastAbs(_velocity.x) > _activeWalkingSpeed || MathHelper.fastAbs(_velocity.z) > _activeWalkingSpeed || MathHelper.fastAbs(_velocity.y) > _activeWalkingSpeed) { double max = Math.max( Math.max(MathHelper.fastAbs(_velocity.x), MathHelper.fastAbs(_velocity.z)), MathHelper.fastAbs(_velocity.y)); double div = max / _activeWalkingSpeed; _velocity.x /= div; _velocity.z /= div; _velocity.y /= div; } /* * Increase the speed of the entity by adding the movement * vector to the acceleration vector. */ _velocity.x += _movementDirection.x; _velocity.y += _movementDirection.y; _velocity.z += _movementDirection.z; double maxGravity = (Double) ConfigurationManager.getInstance().getConfig().get("Player.maxGravity"); double maxGravitySwimming = (Double) ConfigurationManager.getInstance().getConfig().get("Player.maxGravitySwimming"); double gravitySwimming = (Double) ConfigurationManager.getInstance().getConfig().get("Player.gravitySwimming"); double gravity = (Double) ConfigurationManager.getInstance().getConfig().get("Player.gravity"); // Normal gravity if (_gravity > -maxGravity && !_godMode && !_isSwimming) { _gravity -= gravity; } if (_gravity < -maxGravity && !_godMode && !_isSwimming) { _gravity = -maxGravity; } // Gravity under water if (_gravity > -maxGravitySwimming && !_godMode && _isSwimming) { _gravity -= gravitySwimming; } if (_gravity < -maxGravitySwimming && !_godMode && _isSwimming) { _gravity = -maxGravitySwimming; } getPosition().y += _velocity.y; getPosition().y += _gravity; if (!_godMode) { if (verticalHitTest(oldPosition)) { handleVerticalCollision(); double oldGravity = _gravity; _gravity = 0; if (oldGravity <= 0) { // Jumping is only possible, if the entity is standing on ground if (_jump) { _jump = false; _gravity = _jumpIntensity; } // Entity reaches the ground if (!_touchingGround) { Vector3d playerDirection = directionOfReferencePoint(); _footstepSounds[ MathHelper.fastAbs(_parent.getWorldProvider().getRandom().randomInt()) % 5] .playAsSoundEffect( 0.7f + (float) MathHelper.fastAbs( _parent.getWorldProvider().getRandom().randomDouble()) * 0.3f, 0.2f + (float) MathHelper.fastAbs( _parent.getWorldProvider().getRandom().randomDouble()) * 0.3f, false, (float) playerDirection.x, (float) playerDirection.y, (float) playerDirection.z); _touchingGround = true; } } else { _touchingGround = false; } } else { _touchingGround = false; } } else { _gravity = 0f; } oldPosition.set(getPosition()); /* * Update the position of the entity * according to the acceleration vector. */ getPosition().x += _velocity.x; getPosition().z += _velocity.z; _stepCounter += Math.max(MathHelper.fastAbs(_velocity.x), MathHelper.fastAbs(_velocity.z)); /* * Check for horizontal collisions __after__ checking for vertical * collisions. */ if (!_godMode) { if (horizontalHitTest(oldPosition)) { handleHorizontalCollision(); } } }
public IWorldProvider getActiveWorldProvider() { return _worldRenderer.getWorldProvider(); }
/** Init. a new random world. */ public void initWorld(String title, String seed) { final FastRandom random = new FastRandom(); // Get rid of the old world if (_worldRenderer != null) { _worldRenderer.dispose(); _worldRenderer = null; } if (seed == null) { seed = random.randomCharacterString(16); } else if (seed.isEmpty()) { seed = random.randomCharacterString(16); } Terasology.getInstance() .getLogger() .log(Level.INFO, "Creating new World with seed \"{0}\"", seed); // Init. a new world _worldRenderer = new WorldRenderer(title, seed, _entityManager, _localPlayerSys); File entityDataFile = new File(Terasology.getInstance().getWorldSavePath(title), ENTITY_DATA_FILE); _entityManager.clear(); if (entityDataFile.exists()) { try { _entityManager.load(entityDataFile, EntityManager.SaveFormat.Binary); } catch (IOException e) { _logger.log(Level.SEVERE, "Failed to load entity data", e); } } LocalPlayer localPlayer = null; Iterator<EntityRef> iterator = _entityManager.iteratorEntities(LocalPlayerComponent.class).iterator(); if (iterator.hasNext()) { localPlayer = new LocalPlayer(iterator.next()); } else { PlayerFactory playerFactory = new PlayerFactory(_entityManager); localPlayer = new LocalPlayer( playerFactory.newInstance( new Vector3f(_worldRenderer.getWorldProvider().nextSpawningPoint()))); } _worldRenderer.setPlayer(localPlayer); // Create the first Portal if it doesn't exist yet _worldRenderer.initPortal(); fastForwardWorld(); CoreRegistry.put(WorldRenderer.class, _worldRenderer); CoreRegistry.put(IWorldProvider.class, _worldRenderer.getWorldProvider()); CoreRegistry.put(LocalPlayer.class, _worldRenderer.getPlayer()); CoreRegistry.put(Camera.class, _worldRenderer.getActiveCamera()); CoreRegistry.put(BulletPhysicsRenderer.class, _worldRenderer.getBulletRenderer()); for (ComponentSystem system : _componentSystemManager.iterateAll()) { system.initialise(); } }