implement first person hand

(cherry picked from commit bfe5a2eaca2858a7ccde1df847e2148dd79f4045)
This commit is contained in:
LabyStudio
2022-05-02 02:45:24 +02:00
parent 230ea8d11e
commit 800134b26b
18 changed files with 345 additions and 114 deletions
+9 -3
View File
@@ -3,8 +3,10 @@ export default class GameSettings {
constructor() {
this.crouching = 'ShiftLeft';
this.sprinting = 'ControlLeft';
this.togglePerspective = 'F5';
this.togglePerspective = 'F5';
this.thirdPersonView = 0;
this.fov = 70;
this.viewBobbing = true;
}
load() {
@@ -15,7 +17,11 @@ export default class GameSettings {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) {
this[prop] = c.substring(nameEQ.length, c.length);
let value = c.substring(nameEQ.length, c.length);
if (value.match(/^[0-9]+$/)) {
value = parseInt(value);
}
this[prop] = value;
}
}
}
@@ -23,7 +29,7 @@ export default class GameSettings {
save() {
for (let prop in this) {
document.cookie = prop + "=" + (this[prop] || "") + "; path=/; expires=Fri, 31 Dec 9999 23:59:59 GMT";
document.cookie = prop + "=" + this[prop] + "; path=/; expires=Fri, 31 Dec 9999 23:59:59 GMT";
}
}
+1 -1
View File
@@ -66,7 +66,7 @@ export default class GameWindow {
});
// Mouse buttons
document.addEventListener('click', function (event) {
document.addEventListener('mousedown', function (event) {
// Create sound engine (It has to be created after user interaction)
if (!minecraft.soundManager.isCreated()) {
minecraft.soundManager.create(minecraft.worldRenderer);
+4
View File
@@ -192,6 +192,9 @@ export default class Minecraft {
// Tick world
this.world.onTick();
// Tick renderer
this.worldRenderer.onTick();
// Tick the player
this.player.onUpdate();
}
@@ -218,6 +221,7 @@ export default class Minecraft {
if (button === this.settings.togglePerspective) {
this.settings.thirdPersonView = (this.settings.thirdPersonView + 1) % 3;
this.settings.save();
}
}
+4 -1
View File
@@ -7,7 +7,7 @@ export default class Entity {
this.minecraft = minecraft;
this.world = world;
this.group = new THREE.Object3D();
this.renderer = this.minecraft.worldRenderer.entityRenderManager.createEntityRendererByEntity(this);
this.x = 0;
this.y = 0;
@@ -30,6 +30,7 @@ export default class Entity {
this.prevRotationYaw = 0;
this.prevRotationPitch = 0;
this.prevDistanceWalked = 0;
this.distanceWalked = 0;
this.nextStepDistance = 1;
@@ -47,6 +48,8 @@ export default class Entity {
this.prevY = this.y;
this.prevZ = this.z;
this.prevDistanceWalked = this.distanceWalked;
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
@@ -24,9 +24,11 @@ export default class EntityLiving extends Entity {
this.prevRotationYawHead = 0;
this.prevRenderYawOffset = 0;
this.limbSwing = 0;
this.limbSwingAmount = 0;
this.prevLimbSwingAmount = 0;
this.limbSwingProgress = 0;
this.limbSwingStrength = 0;
this.prevLimbSwingStrength = 0;
this.health = 20.0;
}
onUpdate() {
@@ -112,7 +114,7 @@ export default class EntityLiving extends Entity {
}
}
this.prevLimbSwingAmount = this.limbSwingAmount;
this.prevLimbSwingStrength = this.limbSwingStrength;
let motionX = this.x - this.prevX;
let motionZ = this.z - this.prevZ;
@@ -121,8 +123,8 @@ export default class EntityLiving extends Entity {
if (distance > 1.0) {
distance = 1.0;
}
this.limbSwingAmount += (distance - this.limbSwingAmount) * 0.4;
this.limbSwing += this.limbSwingAmount;
this.limbSwingStrength += (distance - this.limbSwingStrength) * 0.4;
this.limbSwingProgress += this.limbSwingStrength;
}
onEntityUpdate() {
@@ -130,6 +132,11 @@ export default class EntityLiving extends Entity {
this.prevRotationYawHead = this.rotationYawHead;
this.prevSwingProgress = this.swingProgress;
this.prevRenderArmYaw = this.renderArmYaw;
this.prevRenderArmPitch = this.renderArmPitch;
this.renderArmPitch = (this.renderArmPitch + (this.rotationPitch - this.renderArmPitch) * 0.5);
this.renderArmYaw = (this.renderArmYaw + (this.rotationYaw - this.renderArmYaw) * 0.5);
this.updateArmSwingProgress();
super.onEntityUpdate();
@@ -191,6 +198,14 @@ export default class EntityLiving extends Entity {
this.swingProgress = this.swingProgressInt / swingAnimationEnd;
}
getSwingProgress(partialTicks) {
let swingProgressDiff = this.swingProgress - this.prevSwingProgress;
if (swingProgressDiff < 0.0) {
swingProgressDiff++;
}
return this.prevSwingProgress + swingProgressDiff * partialTicks;
}
computeAngleWithBound(value, subtract, limit) {
let wrapped = MathHelper.wrapAngleTo180(value - subtract);
if (wrapped < -limit) {
@@ -31,6 +31,18 @@ export default class PlayerEntity extends EntityLiving {
this.prevFovModifier = 0;
this.fovModifier = 0;
this.timeFovChanged = 0;
this.renderArmPitch = 0;
this.renderArmYaw = 0;
this.prevRenderArmPitch = 0;
this.prevRenderArmYaw = 0;
// For first person bobbing
this.cameraYaw = 0;
this.cameraPitch = 0;
this.prevCameraYaw = 0;
this.prevCameraPitch = 0;
}
respawn() {
@@ -78,6 +90,9 @@ export default class PlayerEntity extends EntityLiving {
}
onLivingUpdate() {
this.prevCameraYaw = this.cameraYaw;
this.prevCameraPitch = this.cameraPitch;
if (this.sprintToggleTimer > 0) {
--this.sprintToggleTimer;
}
@@ -127,6 +142,21 @@ export default class PlayerEntity extends EntityLiving {
if (this.sprinting) {
this.jumpMovementFactor = this.jumpMovementFactor + this.speedInAir * 0.3;
}
let speedXZ = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
let speedY = (Math.atan(-this.motionY * 0.2) * 15.0);
if (speedXZ > 0.1) {
speedXZ = 0.1;
}
if (!this.onGround || this.health <= 0.0) {
speedXZ = 0.0;
}
if (this.onGround || this.health <= 0.0) {
speedY = 0.0;
}
this.cameraYaw += (speedXZ - this.cameraYaw) * 0.4;
this.cameraPitch += (speedY - this.cameraPitch) * 0.8;
}
isInWater() {
@@ -18,11 +18,6 @@ export default class IngameOverlay extends Gui {
this.renderCrosshair(stack, this.window.width / 2, this.window.height / 2)
}
// Render holding item
if (this.minecraft.settings.thirdPersonView === 0) {
this.minecraft.itemRenderer.renderItemInHand();
}
// Render hotbar
this.renderHotbar(stack, this.window.width / 2 - 91, this.window.height - 22);
@@ -260,7 +260,7 @@ export default class BlockRenderer {
}
}
renderBlockInHand(group, block, brightness) {
renderBlockInHandThirdPerson(group, block, brightness) {
this.tessellator.startDrawing();
// Render block
@@ -35,6 +35,10 @@ export default class WorldRenderer {
// Entity render manager
this.entityRenderManager = new EntityRenderManager(this);
this.equippedProgress = 0;
this.prevEquippedProgress = 0;
this.itemToRender = 0;
this.initialize();
}
@@ -51,6 +55,10 @@ export default class WorldRenderer {
this.scene = new THREE.Scene();
this.scene.matrixAutoUpdate = false;
// Create overlay for first person model rendering
this.overlay = new THREE.Scene();
this.overlay.matrixAutoUpdate = false;
// Create web renderer
this.webRenderer = new THREE.WebGLRenderer({
canvas: this.window.canvas,
@@ -77,6 +85,9 @@ export default class WorldRenderer {
color: 0x000000,
}));
this.scene.add(this.blockHitBox);
// Hand group
this.handGroup = new THREE.Object3D();
}
render(partialTicks) {
@@ -95,18 +106,57 @@ export default class WorldRenderer {
// Render target block
this.renderBlockHitBox(player, partialTicks);
// Hide all entities and make them visible during rendering
for (let entity of this.minecraft.world.entities) {
entity.renderer.group.visible = false;
}
// Render entities
for (let entity of this.minecraft.world.entities) {
if (entity === player && this.minecraft.settings.thirdPersonView === 0) {
entity.group.clear(); // Remove entity from scene
delete entity.group.buildMeta; // To trigger a rebuild on the next render
continue;
}
this.renderEntity(entity, partialTicks);
// Render entity
entity.renderer.render(entity, partialTicks);
entity.renderer.group.visible = true;
}
// Render hand
this.renderHand(partialTicks);
// Render actual scene
this.webRenderer.render(this.scene, this.camera);
// Render overlay with a static FOV
this.camera.fov = this.minecraft.settings.fov;
this.camera.updateProjectionMatrix();
this.webRenderer.render(this.overlay, this.camera);
}
onTick() {
this.prevEquippedProgress = this.equippedProgress;
let player = this.minecraft.player;
let itemStack = player.inventory.getItemInSelectedSlot();
let showHand = false;
if (this.itemToRender != null && itemStack != null) {
if (this.itemToRender !== itemStack) {
showHand = true;
}
} else if (this.itemToRender == null && itemStack == null) {
showHand = false;
} else {
showHand = true;
}
// Update equip progress
this.equippedProgress += MathHelper.clamp((showHand ? 0.0 : 1.0) - this.equippedProgress, -0.4, 0.4);
if (this.equippedProgress < 0.1) {
this.itemToRender = itemStack;
}
}
orientCamera(partialTicks) {
@@ -151,7 +201,7 @@ export default class WorldRenderer {
this.frustum.setFromProjectionMatrix(new THREE.Matrix4().multiplyMatrices(this.camera.projectionMatrix, this.camera.matrixWorldInverse));
// Update FOV
this.camera.fov = 85 + player.getFOVModifier();
this.camera.fov = this.minecraft.settings.fov + player.getFOVModifier();
this.camera.updateProjectionMatrix();
// Setup fog
@@ -294,6 +344,83 @@ export default class WorldRenderer {
this.skyGroup.rotation.set(angle * Math.PI * 2 + Math.PI / 2, 0, 0);
}
renderHand(partialTicks) {
// Hide hand before rendering
let player = this.minecraft.player;
let stack = player.renderer.handGroup;
stack.visible = false;
// Hide in third person
if (this.minecraft.settings.thirdPersonView !== 0) {
return;
}
// Apply matrix mode (Put object in front of camera)
stack.position.copy(this.camera.position);
stack.rotation.copy(this.camera.rotation);
stack.rotation.order = 'ZYX';
// Scale down
stack.scale.set(0.0625, 0.0625, 0.0625);
let equipProgress = this.prevEquippedProgress + (this.equippedProgress - this.prevEquippedProgress) * partialTicks;
let swingProgress = player.getSwingProgress(partialTicks);
let pitchArm = player.prevRenderArmPitch + (player.renderArmPitch - player.prevRenderArmPitch) * partialTicks;
let yawArm = player.prevRenderArmYaw + (player.renderArmYaw - player.prevRenderArmYaw) * partialTicks;
let factor = 0.8;
let zOffset = Math.sin(swingProgress * Math.PI);
let yOffset = Math.sin(Math.sqrt(swingProgress) * Math.PI * 2.0);
let xOffset = Math.sin(Math.sqrt(swingProgress) * Math.PI);
let yRotation = Math.sin(Math.sqrt(swingProgress) * Math.PI);
let zRotation = Math.sin(swingProgress * swingProgress * Math.PI);
// Bobbing animation
if (this.minecraft.settings.viewBobbing) {
let walked = -(player.prevDistanceWalked + (player.distanceWalked - player.prevDistanceWalked) * partialTicks);
let yaw = player.prevCameraYaw + (player.cameraYaw - player.prevCameraYaw) * partialTicks;
let pitch = player.prevCameraPitch + (player.cameraPitch - player.prevCameraPitch) * partialTicks;
this.translate(
stack,
Math.sin(walked * 3.141593) * yaw * 0.5,
-Math.abs(Math.cos(walked * Math.PI) * yaw),
0.0
);
stack.rotateZ(MathHelper.toRadians(Math.sin(walked * Math.PI) * yaw * 3.0));
stack.rotateX(MathHelper.toRadians(Math.abs(Math.cos(walked * Math.PI - 0.2) * yaw) * 5.0));
stack.rotateX(MathHelper.toRadians(pitch));
}
// Camera rotation movement
stack.rotateX(MathHelper.toRadians((player.rotationPitch - pitchArm) * 0.1));
stack.rotateY(MathHelper.toRadians((player.rotationYaw - yawArm) * 0.1));
// Initial offset on screen
this.translate(stack, -xOffset * 0.3, yOffset * 0.4, -zOffset * 0.4);
this.translate(stack, 0.8 * factor, -0.75 * factor - (1.0 - equipProgress) * 0.6, -0.9 * factor);
// Rotation of hand
stack.rotateY(MathHelper.toRadians(45));
stack.rotateY(MathHelper.toRadians(yRotation * 70));
stack.rotateZ(MathHelper.toRadians(-zRotation * 20));
// Post transform
this.translate(stack, -1, 3.6, 3.5);
stack.rotateZ(MathHelper.toRadians(120));
stack.rotateX(MathHelper.toRadians(200));
stack.rotateY(MathHelper.toRadians(-135));
this.translate(stack, 5.6, 0.0, 0.0);
if (this.itemToRender === 0) {
// Render hand
player.renderer.renderRightArm(player, partialTicks);
} else {
// Render item
}
}
renderBlockHitBox(player, partialTicks) {
let hitResult = player.rayTrace(5, partialTicks);
let hitBoxVisible = !(hitResult === null);
@@ -333,8 +460,9 @@ export default class WorldRenderer {
}
}
renderEntity(entity, partialTicks) {
let entityRenderer = this.entityRenderManager.getEntityRendererByEntity(entity);
entityRenderer.render(entity, partialTicks);
translate(stack, x, y, z) {
stack.translateX(x);
stack.translateY(y);
stack.translateZ(z);
}
}
@@ -7,14 +7,14 @@ export default class EntityRenderManager {
this.worldRenderer = worldRenderer;
this.renderers = [];
this.push(PlayerEntity, new PlayerRenderer(worldRenderer));
this.push(PlayerEntity, PlayerRenderer);
}
push(entityType, entityRenderer) {
this.renderers[entityType.name] = entityRenderer;
}
getEntityRendererByEntity(entity) {
return this.renderers[entity.constructor.name];
createEntityRendererByEntity(entity) {
return new this.renderers[entity.constructor.name].prototype.constructor(this.worldRenderer);
}
}
@@ -6,22 +6,22 @@ export default class EntityRenderer {
constructor(model) {
this.model = model;
this.tessellator = new Tessellator();
this.group = new THREE.Object3D();
}
rebuild(entity) {
// Create meta for group
let group = entity.group;
let meta = {};
this.fillMeta(entity, meta);
group.buildMeta = meta;
this.group.buildMeta = meta;
// Clear meshes
group.clear();
this.group.clear();
// Apply brightness and rebuild
let brightness = group.buildMeta.brightness;
let brightness = this.group.buildMeta.brightness;
this.tessellator.setColor(brightness, brightness, brightness);
this.model.rebuild(this.tessellator, group);
this.model.rebuild(this.tessellator, this.group);
}
fillMeta(entity, meta) {
@@ -30,30 +30,25 @@ export default class EntityRenderer {
}
isRebuildRequired(entity) {
let group = entity.group;
if (typeof group.buildMeta === "undefined") {
if (typeof this.group.buildMeta === "undefined") {
return true;
}
// Compare meta of group
let currentMeta = {};
this.fillMeta(entity, currentMeta);
let previousMeta = group.buildMeta;
let previousMeta = this.group.buildMeta;
return JSON.stringify(currentMeta) !== JSON.stringify(previousMeta);
}
render(entity, partialTicks) {
if (this.isRebuildRequired(entity)) {
this.rebuild(entity);
}
let group = entity.group;
this.prepareModel(entity);
let rotationBody = this.interpolateRotation(entity.prevRenderYawOffset, entity.renderYawOffset, partialTicks);
let rotationHead = this.interpolateRotation(entity.prevRotationYawHead, entity.rotationYawHead, partialTicks);
let limbSwing = entity.prevLimbSwingAmount + (entity.limbSwingAmount - entity.prevLimbSwingAmount) * partialTicks;
let limbSwingAmount = entity.limbSwing - entity.limbSwingAmount * (1.0 - partialTicks);
let limbSwingStrength = entity.prevLimbSwingStrength + (entity.limbSwingStrength - entity.prevLimbSwingStrength) * partialTicks;
let limbSwing = entity.limbSwingProgress - entity.limbSwingStrength * (1.0 - partialTicks);
let yaw = rotationHead - rotationBody;
let pitch = entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks;
@@ -64,20 +59,21 @@ export default class EntityRenderer {
let interpolatedZ = entity.prevZ + (entity.z - entity.prevZ) * partialTicks;
// Translate using interpolated position
group.position.setX(interpolatedX);
group.position.setY(interpolatedY + 1.4);
group.position.setZ(interpolatedZ);
this.group.position.setX(interpolatedX);
this.group.position.setY(interpolatedY + 1.4);
this.group.position.setZ(interpolatedZ);
// Actual size of the entity
let scale = 7.0 / 120.0;
group.scale.set(-scale, -scale, scale);
this.group.scale.set(-scale, -scale, scale);
// Rotate entity model
group.rotation.y = MathHelper.toRadians(-rotationBody + 180);
this.group.rotation.y = MathHelper.toRadians(-rotationBody + 180);
// Render entity model
let timeAlive = entity.ticksExisted + partialTicks;
this.model.render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch, partialTicks);
let stack = entity.renderer.group;
this.model.render(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks);
}
interpolateRotation(prevValue, value, partialTicks) {
@@ -90,4 +86,10 @@ export default class EntityRenderer {
return prevValue + partialTicks * factor;
}
prepareModel(entity) {
if (this.isRebuildRequired(entity)) {
this.rebuild(entity);
}
}
}
@@ -13,6 +13,11 @@ export default class PlayerRenderer extends EntityRenderer {
this.textureCharacter = new THREE.TextureLoader().load('src/resources/char.png');
this.textureCharacter.magFilter = THREE.NearestFilter;
this.textureCharacter.minFilter = THREE.NearestFilter;
// First person right-hand holder
this.handModel = null;
this.handGroup = new THREE.Object3D();
this.worldRenderer.overlay.add(this.handGroup);
}
rebuild(entity) {
@@ -22,16 +27,52 @@ export default class PlayerRenderer extends EntityRenderer {
// Render item in hand
let group = this.model.rightArm.bone;
let id = entity.inventory.getItemInSelectedSlot();
if (id !== 0) {
if (id !== 0 && this.worldRenderer.minecraft.settings.thirdPersonView !== 0) {
let block = Block.getById(id);
this.worldRenderer.blockRenderer.renderBlockInHand(group, block, entity.getEntityBrightness());
this.worldRenderer.blockRenderer.renderBlockInHandThirdPerson(group, block, entity.getEntityBrightness());
}
// Create first person right hand and attach it to the holder
this.handGroup.clear();
this.handModel = this.model.rightArm.clone();
this.handGroup.add(this.handModel.bone);
// Copy material and update depth test of the hand
let mesh = this.handModel.bone.children[0];
mesh.renerOrder = 999;
mesh.material = mesh.material.clone();
mesh.material.depthTest = false;
mesh.material.depthWrite = false;
}
render(entity, partialTicks) {
let swingProgress = entity.swingProgress - entity.prevSwingProgress;
if (swingProgress < 0.0) {
swingProgress++;
}
this.model.swingProgress = entity.prevSwingProgress + swingProgress * partialTicks;
this.model.hasItemInHand = entity.inventory.getItemInSelectedSlot() !== 0;
this.model.isSneaking = entity.sneaking;
super.render(entity, partialTicks);
}
renderRightArm(player, partialTicks) {
// Make sure the model is created
this.prepareModel(player);
// Set transform of renderer
this.model.swingProgress = 0;
this.model.hasItemInHand = false;
this.model.isSneaking = false;
this.model.setRotationAngles(player, 0, 0, 0, 0, 0, 0);
this.handModel.copyTransformOf(this.model.rightArm);
// Render the model
this.handGroup.visible = true;
this.handModel.render();
}
fillMeta(entity, meta) {
super.fillMeta(entity, meta);
meta.itemInHand = entity.inventory.getItemInSelectedSlot();
@@ -1,5 +1,3 @@
import Block from "../../world/block/Block.js";
export default class ItemRenderer {
constructor(minecraft, window) {
@@ -7,15 +5,13 @@ export default class ItemRenderer {
this.window = window;
this.items = [];
this.itemInHand = null;
this.itemInHandGroup = new THREE.Object3D();
}
initialize() {
// Create item camera
this.camera = new THREE.OrthographicCamera(0, 0, 0, 0, 0, 300);
this.camera.near = 0;
this.camera.far = 15;
this.camera.far = 100;
this.camera.rotation.order = 'ZYX';
this.camera.up = new THREE.Vector3(0, 1, 0);
@@ -37,8 +33,6 @@ export default class ItemRenderer {
this.webRenderer.sortObjects = false;
this.webRenderer.setClearColor(0x000000, 0);
this.webRenderer.clear();
this.scene.add(this.itemInHandGroup);
}
render(partialTicks) {
@@ -54,28 +48,6 @@ export default class ItemRenderer {
this.webRenderer.render(this.scene, this.camera);
}
renderItemInHand() {
let typeId = this.minecraft.player.inventory.getItemInSelectedSlot();
if (typeId === this.itemInHand) {
return; // Skip rebuilding if the item hasn't changed
}
// Clear previous mesh
this.itemInHandGroup.clear();
// Should render hand or item
if (typeId === 0) {
} else {
let block = Block.getById(typeId);
// this.minecraft.worldRenderer.blockRenderer.renderBlockInHand(block, this.itemInHandGroup, 1);
}
// Store item in hand meta
this.itemInHand = typeId;
}
renderItemInGui(renderId, block, x, y) {
let meta = this.items[renderId];
if (typeof meta === "undefined") {
@@ -10,8 +10,12 @@ export default class ModelBase {
}
render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch) {
entity.group.updateMatrix();
render(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks) {
stack.updateMatrix();
}
setRotationAngles(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks) {
}
}
@@ -10,6 +10,10 @@ export default class ModelPlayer extends ModelBase {
constructor() {
super();
this.swingProgress = 0;
this.hasItemInHand = false;
this.isSneaking = false;
let width = 64;
let height = 32;
@@ -59,20 +63,32 @@ export default class ModelPlayer extends ModelBase {
this.rightLeg.rebuild(tessellator, group);
}
render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch, partialTicks) {
let group = entity.group;
render(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks) {
this.setRotationAngles(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks);
// Render cubes
this.head.render();
this.body.render();
this.rightArm.render();
this.leftArm.render();
this.rightLeg.render();
this.leftLeg.render();
super.render(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks);
}
setRotationAngles(stack, limbSwing, limbSwingStrength, timeAlive, yaw, pitch, partialTicks) {
// Head rotation
this.head.rotateAngleY = MathHelper.toRadians(yaw);
this.head.rotateAngleX = MathHelper.toRadians(pitch);
// Limb swing leg animation
this.rightArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662 + Math.PI) * 2.0 * limbSwing * 0.5;
this.leftArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662) * 2.0 * limbSwing * 0.5;
this.rightArm.rotateAngleX = Math.cos(limbSwing * 0.6662 + Math.PI) * 2.0 * limbSwingStrength * 0.5;
this.leftArm.rotateAngleX = Math.cos(limbSwing * 0.6662) * 2.0 * limbSwingStrength * 0.5;
this.rightArm.rotateAngleZ = 0.0;
this.leftArm.rotateAngleZ = 0.0;
this.rightLeg.rotateAngleX = Math.cos(limbSwingAmount * 0.6662) * 1.4 * limbSwing;
this.leftLeg.rotateAngleX = Math.cos(limbSwingAmount * 0.6662 + Math.PI) * 1.4 * limbSwing;
this.rightLeg.rotateAngleX = Math.cos(limbSwing * 0.6662) * 1.4 * limbSwingStrength;
this.leftLeg.rotateAngleX = Math.cos(limbSwing * 0.6662 + Math.PI) * 1.4 * limbSwingStrength;
this.rightLeg.rotateAngleY = 0.0;
this.leftLeg.rotateAngleY = 0.0;
@@ -82,18 +98,12 @@ export default class ModelPlayer extends ModelBase {
this.leftArm.rotateAngleY = 0.0;
// Held item animation
if (entity.inventory.getItemInSelectedSlot() !== 0) {
if (this.hasItemInHand) {
this.rightArm.rotateAngleX = this.rightArm.rotateAngleX * 0.5 - (Math.PI / 10);
}
// Swing progress
let swingProgress = entity.swingProgress - entity.prevSwingProgress;
if (swingProgress < 0.0) {
swingProgress++;
}
let interpolatedSwingProgress = entity.prevSwingProgress + swingProgress * partialTicks;
if (interpolatedSwingProgress > -9990.0) {
let swingProgress = interpolatedSwingProgress;
if (this.swingProgress > -9990.0) {
let swingProgress = this.swingProgress;
this.body.rotateAngleY = Math.sin(Math.sqrt(swingProgress) * Math.PI * 2.0) * 0.2;
@@ -106,21 +116,21 @@ export default class ModelPlayer extends ModelBase {
this.leftArm.rotateAngleY += this.body.rotateAngleY;
this.leftArm.rotateAngleX += this.body.rotateAngleY;
swingProgress = 1.0 - interpolatedSwingProgress;
swingProgress = 1.0 - swingProgress;
swingProgress = swingProgress * swingProgress;
swingProgress = swingProgress * swingProgress;
swingProgress = 1.0 - swingProgress;
let value1 = Math.sin(swingProgress * Math.PI);
let value2 = Math.sin(interpolatedSwingProgress * Math.PI) * -(this.head.rotateAngleX - 0.7) * 0.75;
let value2 = Math.sin(swingProgress * Math.PI) * -(this.head.rotateAngleX - 0.7) * 0.75;
this.rightArm.rotateAngleX = (this.rightArm.rotateAngleX - (value1 * 1.2 + value2));
this.rightArm.rotateAngleY += this.body.rotateAngleY * 2.0;
this.rightArm.rotateAngleZ += Math.sin(interpolatedSwingProgress * Math.PI) * -0.4;
this.rightArm.rotateAngleZ += Math.sin(swingProgress * Math.PI) * -0.4;
}
// Sneaking animation
if (entity.sneaking) {
if (this.isSneaking) {
this.body.rotateAngleX = 0.5;
this.rightArm.rotateAngleX += 0.4;
this.leftArm.rotateAngleX += 0.4;
@@ -130,7 +140,7 @@ export default class ModelPlayer extends ModelBase {
this.leftLeg.rotationPointY = 9.0;
this.head.rotationPointY = 1.0;
group.translateY(-0.2);
stack.translateY(-0.2);
} else {
this.body.rotateAngleX = 0.0;
this.rightLeg.rotationPointZ = 0.1;
@@ -145,16 +155,6 @@ export default class ModelPlayer extends ModelBase {
this.leftArm.rotateAngleZ -= Math.cos(timeAlive * 0.09) * 0.05 + 0.05;
this.rightArm.rotateAngleX += Math.sin(timeAlive * 0.067) * 0.05;
this.leftArm.rotateAngleX -= Math.sin(timeAlive * 0.067) * 0.05;
// Render cubes
this.head.render();
this.body.render();
this.rightArm.render();
this.leftArm.render();
this.rightLeg.render();
this.leftLeg.render();
super.render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch);
}
}
@@ -262,4 +262,31 @@ export default class ModelRenderer {
this.bone.updateMatrix();
}
clone() {
let modelRenderer = new ModelRenderer(this.name, this.textureWidth, this.textureHeight);
modelRenderer.bone = this.bone.clone();
modelRenderer.textureOffsetX = this.textureOffsetX;
modelRenderer.textureOffsetY = this.textureOffsetY;
modelRenderer.cubes = this.cubes;
modelRenderer.copyTransformOf(this);
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i];
modelRenderer.addChild(child.clone());
}
return modelRenderer;
}
copyTransformOf(modelRenderer) {
this.rotationPointX = modelRenderer.rotationPointX;
this.rotationPointY = modelRenderer.rotationPointY;
this.rotationPointZ = modelRenderer.rotationPointZ;
this.scaleX = modelRenderer.scaleX;
this.scaleY = modelRenderer.scaleY;
this.scaleZ = modelRenderer.scaleZ;
this.rotateAngleX = modelRenderer.rotateAngleX;
this.rotateAngleY = modelRenderer.rotateAngleY;
this.rotateAngleZ = modelRenderer.rotateAngleZ;
}
}
+2 -2
View File
@@ -521,13 +521,13 @@ export default class World {
addEntity(entity) {
this.entities.push(entity);
this.group.add(entity.group);
this.group.add(entity.renderer.group);
}
removeEntityById(id) {
let entity = this.getEntityById(id);
this.entities.remove(entity);
this.group.remove(entity.group);
this.group.remove(entity.renderer.group);
}
getEntityById(id) {
+5 -1
View File
@@ -1,5 +1,9 @@
export default class MathHelper {
static clamp(number, min, max) {
return Math.min(Math.max(number, min), max);
}
/**
* Returns the greatest integer less than or equal to the double argument
*/
@@ -14,7 +18,7 @@ export default class MathHelper {
static toRadians(degree) {
return degree * (Math.PI / 180);
};
}
static calculateCelestialAngle(time, partialTicks) {
let modTime = (time % 24000);