implement player and movement input

This commit is contained in:
LabyStudio
2022-01-31 11:10:47 +01:00
parent ddc7480529
commit 7f4d7f88bf
9 changed files with 875 additions and 21 deletions
+29 -2
View File
@@ -4,8 +4,13 @@ window.GameWindow = class {
this.renderer = renderer;
this.canvasWrapperId = canvasWrapperId;
this.mouseMotionX = 0;
this.mouseMotionY = 0;
this.mouseLocked = false;
// Add web renderer canvas to wrapper
document.getElementById(this.canvasWrapperId).appendChild(renderer.canvasElement);
let canvas = renderer.canvasElement;
document.getElementById(this.canvasWrapperId).appendChild(canvas);
// Init
this.initialize();
@@ -13,10 +18,23 @@ window.GameWindow = class {
// On resize
let scope = this;
window.addEventListener('resize', _ => scope.initialize(), false);
// Request focus
canvas.onclick = function () {
canvas.requestPointerLock();
}
// Focus listener
document.addEventListener('pointerlockchange', _ => this.onFocusChanged(), false);
// Mouse motion
document.addEventListener('mousemove', event => this.onMouseMove(event), false);
}
initialize() {
// Create keyboard
Keyboard.create();
// Get canvas size
let canvasElement = document.getElementById(this.canvasWrapperId);
this.canvasWidth = canvasElement.offsetWidth;
@@ -27,4 +45,13 @@ window.GameWindow = class {
this.renderer.camera.updateProjectionMatrix();
this.renderer.webRenderer.setSize(this.canvasWidth, this.canvasHeight);
}
onFocusChanged() {
this.mouseLocked = document.pointerLockElement === this.renderer.canvasElement;
}
onMouseMove(event) {
this.mouseMotionX = -event.movementX;
this.mouseMotionY = event.movementY;
}
}
+22 -5
View File
@@ -11,9 +11,14 @@ window.Minecraft = class {
this.frames = 0;
this.lastTime = Date.now();
// Create world
this.world = new World();
this.worldRenderer.scene.add(this.world.group);
// Create player
this.player = new Player(this.world);
// Initialize
this.init();
}
@@ -27,12 +32,12 @@ window.Minecraft = class {
requestAnimationFrame(function () {
if (scope.running) {
scope.requestNextFrame();
scope.onRender();
scope.onLoop();
}
});
}
onRender() {
onLoop() {
// Update the timer
this.timer.advanceTime();
@@ -42,22 +47,34 @@ window.Minecraft = class {
}
// Render the game
this.worldRenderer.render(this.timer.partialTicks);
this.onRender(this.timer.partialTicks);
// Increase rendered frame
this.frames++;
// Loop if a second passed
while (Date.now() >= this.lastTime + 1000) {
console.log(this.frames + " fps");
//console.log(this.frames + " fps");
this.lastTime += 1000;
this.frames = 0;
}
}
onTick() {
onRender(partialTicks) {
if (this.window.mouseLocked) {
this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY);
this.window.mouseMotionX = 0;
this.window.mouseMotionY = 0;
}
// Render the game
this.worldRenderer.render(partialTicks);
}
onTick() {
this.player.onTick();
}
}
+476
View File
@@ -0,0 +1,476 @@
window.Player = class {
constructor(world) {
this.world = world;
this.prevX = 0;
this.prevY = 0;
this.prevZ = 0;
this.x = 0;
this.y = 0;
this.z = 0;
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
this.yaw = 0;
this.pitch = 0;
this.onGround = false;
this.collision = false;
this.jumpMovementFactor = 0.02;
this.speedInAir = 0.02;
this.flySpeed = 0.05;
this.stepHeight = 0.5;
this.moveForward = 0.0;
this.moveStrafing = 0.0;
this.jumpTicks = 0;
this.flyToggleTimer = 0;
this.sprintToggleTimer = 0;
this.jumping = false;
this.sprinting = false;
this.sneaking = false;
this.flying = false;
this.prevFovModifier = 0;
this.fovModifier = 0;
this.timeFovChanged = 0;
this.resetPos();
}
resetPos() {
this.setPos(0, 15, 0);
}
setPos(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
let w = 0.3;
let h = 0.9;
this.boundingBox = new BoundingBox(x - w, y - h, z - w, x + w, y + h, z + w);
}
turn(motionX, motionY) {
this.yaw = this.yaw + motionX * 0.15;
this.pitch = this.pitch - motionY * 0.15;
if (this.pitch < -90.0) {
this.pitch = -90.0;
}
if (this.pitch > 90.0) {
this.pitch = 90.0;
}
}
onTick() {
let prevMoveForward = this.moveForward;
let prevJumping = this.jumping;
this.updateKeyboardInput();
// Toggle jumping
if (!prevJumping && this.jumping) {
if (this.flyToggleTimer === 0) {
this.flyToggleTimer = 7;
} else {
this.flying = !this.flying;
this.flyToggleTimer = 0;
this.updateFOVModifier();
}
}
// Toggle sprint
if (prevMoveForward === 0 && this.moveForward > 0) {
if (this.sprintToggleTimer === 0) {
this.sprintToggleTimer = 7;
} else {
this.sprinting = true;
this.sprintToggleTimer = 0;
this.updateFOVModifier();
}
}
if (this.jumpTicks > 0) {
--this.jumpTicks;
}
if (this.flyToggleTimer > 0) {
--this.flyToggleTimer;
}
if (this.sprintToggleTimer > 0) {
--this.sprintToggleTimer;
}
this.prevX = this.x;
this.prevY = this.y;
this.prevZ = this.z;
// Stop if too slow
if (Math.abs(this.motionX) < 0.003) {
this.motionX = 0.0;
}
if (Math.abs(this.motionY) < 0.003) {
this.motionY = 0.0;
}
if (Math.abs(this.motionZ) < 0.003) {
this.motionZ = 0.0;
}
// Jump
if (this.jumping) {
if (this.isInWater()) {
this.motionY += 0.04;
} else if (this.onGround && this.jumpTicks === 0) {
this.jump();
this.jumpTicks = 10;
}
} else {
this.jumpTicks = 0;
}
this.moveStrafing *= 0.98;
this.moveForward *= 0.98;
if (this.flying) {
this.travelFlying(this.moveForward, 0, this.moveStrafing);
} else {
if (this.isInWater()) {
// Is inside of water
this.travelInWater(this.moveForward, 0, this.moveStrafing);
} else {
// Is on land
this.travel(this.moveForward, 0, this.moveStrafing);
}
}
this.jumpMovementFactor = this.speedInAir;
if (this.sprinting) {
this.jumpMovementFactor = this.jumpMovementFactor + this.speedInAir * 0.3;
if (this.moveForward <= 0 || this.collision || this.sneaking) {
this.sprinting = false;
this.updateFOVModifier();
}
}
}
isInWater() {
return false;
}
isHeadInWater() {
return false;
}
jump() {
this.motionY = 0.42;
if (this.sprinting) {
let radiansYaw = -this.yaw * (Math.PI / 180);
this.motionX -= Math.sin(radiansYaw) * 0.2;
this.motionZ += Math.cos(radiansYaw) * 0.2;
}
}
travelFlying(forward, vertical, strafe) {
// Fly move up and down
if (this.sneaking) {
this.moveStrafing = strafe / 0.3;
this.moveForward = forward / 0.3;
this.motionY -= this.flySpeed * 3.0;
}
if (this.jumping) {
this.motionY += this.flySpeed * 3.0;
}
let prevMotionY = this.motionY;
let prevJumpMovementFactor = this.jumpMovementFactor;
this.jumpMovementFactor = this.flySpeed * (this.sprinting ? 2 : 1);
this.travel(forward, vertical, strafe);
this.motionY = prevMotionY * 0.6;
this.jumpMovementFactor = prevJumpMovementFactor;
if (this.onGround) {
this.flying = false;
}
}
travelInWater(forward, vertical, strafe) {
let slipperiness = 0.8;
let friction = 0.02;
this.moveRelative(forward, vertical, strafe, friction);
this.collision = this.moveCollide(-this.motionX, this.motionY, -this.motionZ);
this.motionX *= slipperiness;
this.motionY *= 0.8;
this.motionZ *= slipperiness;
this.motionY -= 0.02;
}
travel(forward, vertical, strafe) {
let prevSlipperiness = this.getBlockSlipperiness() * 0.91;
let value = 0.16277136 / (prevSlipperiness * prevSlipperiness * prevSlipperiness);
let friction;
if (this.onGround) {
friction = this.getAIMoveSpeed() * value;
} else {
friction = this.jumpMovementFactor;
}
this.moveRelative(forward, vertical, strafe, friction);
// Get new speed
let slipperiness = this.getBlockSlipperiness() * 0.91;
// Move
this.collision = this.moveCollide(-this.motionX, this.motionY, -this.motionZ);
// Gravity
if (!this.flying) {
this.motionY -= 0.08;
}
// Decrease motion
this.motionX *= slipperiness;
this.motionY *= 0.98;
this.motionZ *= slipperiness;
}
getBlockSlipperiness() {
return this.onGround ? 0.6 : 1.0;
}
getAIMoveSpeed() {
return this.sprinting ? 0.13 : 0.1;
}
moveRelative(forward, up, strafe, friction) {
let distance = strafe * strafe + up * up + forward * forward;
if (distance >= 0.0001) {
distance = Math.sqrt(distance);
if (distance < 1.0) {
distance = 1.0;
}
distance = friction / distance;
strafe = strafe * distance;
up = up * distance;
forward = forward * distance;
let yawRadians = -this.yaw * (Math.PI / 180);
let sin = Math.sin(yawRadians);
let cos = Math.cos(yawRadians);
this.motionX += strafe * cos - forward * sin;
this.motionY += up;
this.motionZ += forward * cos + strafe * sin;
}
}
updateKeyboardInput() {
let moveForward = 0.0;
let moveStrafe = 0.0;
let jumping = false;
let sneaking = false;
if (Keyboard.isKeyDown("KeyR")) { // R
this.resetPos();
}
if (Keyboard.isKeyDown("KeyW")) { // W
moveForward++;
}
if (Keyboard.isKeyDown("KeyS")) { // S
moveForward--;
}
if (Keyboard.isKeyDown("KeyA")) { // A
moveStrafe++;
}
if (Keyboard.isKeyDown("KeyD")) { // D
moveStrafe--;
}
if (Keyboard.isKeyDown("Space")) { // Space
jumping = true;
}
if (Keyboard.isKeyDown("ShiftLeft")) { // Shift
if (this.moveForward > 0 && !this.sneaking && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) {
this.sprinting = true;
this.updateFOVModifier();
}
}
if (Keyboard.isKeyDown("KeyQ")) { // Q
sneaking = true;
}
if (sneaking) {
moveStrafe = moveStrafe * 0.3;
moveForward = moveForward * 0.3;
}
this.moveForward = moveForward;
this.moveStrafing = moveStrafe;
this.jumping = jumping;
this.sneaking = sneaking;
}
moveCollide(targetX, targetY, targetZ) {
// Target position
let originalTargetX = targetX;
let originalTargetY = targetY;
let originalTargetZ = targetZ;
if (this.onGround && this.sneaking) {
for (; targetX !== 0.0 && this.world.getCollisionBoxes(this.boundingBox.offset(targetX, -this.stepHeight, 0.0)).length === 0; originalTargetX = targetX) {
if (targetX < 0.05 && targetX >= -0.05) {
targetX = 0.0;
} else if (targetX > 0.0) {
targetX -= 0.05;
} else {
targetX += 0.05;
}
}
for (; targetZ !== 0.0 && this.world.getCollisionBoxes(this.boundingBox.offset(0.0, -this.stepHeight, targetZ)).length === 0; originalTargetZ = targetZ) {
if (targetZ < 0.05 && targetZ >= -0.05) {
targetZ = 0.0;
} else if (targetZ > 0.0) {
targetZ -= 0.05;
} else {
targetZ += 0.05;
}
}
for (; targetX !== 0.0 && targetZ !== 0.0 && this.world.getCollisionBoxes(this.boundingBox.offset(targetX, -this.stepHeight, targetZ)).length === 0; originalTargetZ = targetZ) {
if (targetX < 0.05 && targetX >= -0.05) {
targetX = 0.0;
} else if (targetX > 0.0) {
targetX -= 0.05;
} else {
targetX += 0.05;
}
originalTargetX = targetX;
if (targetZ < 0.05 && targetZ >= -0.05) {
targetZ = 0.0;
} else if (targetZ > 0.0) {
targetZ -= 0.05;
} else {
targetZ += 0.05;
}
}
}
// Get level tiles as bounding boxes
let boundingBoxList = this.world.getCollisionBoxes(this.boundingBox.expand(targetX, targetY, targetZ));
// Move bounding box
for (let aABB in boundingBoxList) {
targetY = boundingBoxList[aABB].clipYCollide(this.boundingBox, targetY);
}
this.boundingBox.move(0.0, targetY, 0.0);
for (let aABB in boundingBoxList) {
targetX = boundingBoxList[aABB].clipXCollide(this.boundingBox, targetX);
}
this.boundingBox.move(targetX, 0.0, 0.0);
for (let aABB in boundingBoxList) {
targetZ = boundingBoxList[aABB].clipZCollide(this.boundingBox, targetZ);
}
this.boundingBox.move(0.0, 0.0, targetZ);
this.onGround = originalTargetY !== targetY && originalTargetY < 0.0;
// Stop motion on collision
if (originalTargetX !== targetX) {
this.motionX = 0.0;
}
if (originalTargetY !== targetY) {
this.motionY = 0.0;
}
if (originalTargetZ !== targetZ) {
this.motionZ = 0.0;
}
// Update position
this.x = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0;
this.y = this.boundingBox.minY;
this.z = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0;
// Horizontal collision?
return originalTargetX !== targetX || originalTargetZ !== targetZ;
}
getEyeHeight() {
return this.sneaking ? 1.50 : 1.62;
}
updateFOVModifier() {
let value = 1.0;
if (this.sprinting) {
value += 1;
}
if (this.flying) {
value *= 1.1;
}
this.setFOVModifier((value - 1.0) * 10);
}
setFOVModifier(fov) {
this.prevFovModifier = this.fovModifier;
this.fovModifier = fov;
this.timeFovChanged = Date.now();
}
getFOVModifier() {
let timePassed = Date.now() - this.timeFovChanged;
let distance = this.prevFovModifier - this.fovModifier;
let duration = 100;
let progress = distance / duration * timePassed;
return timePassed > duration ? this.fovModifier : this.prevFovModifier - progress;
}
getBlockPosX() {
return this.x - (this.x < 0 ? 1 : 0);
}
getBlockPosY() {
return this.y - (this.y < 0 ? 1 : 0);
}
getBlockPosZ() {
return this.z - (this.z < 0 ? 1 : 0);
}
}
@@ -8,8 +8,8 @@ window.WorldRenderer = class {
|| !!document.createElement('canvas').getContext('webgl'));
// Create cameras
this.camera = new THREE.PerspectiveCamera(85, 1, 1, 10000);
this.camera.position.set(0, 3, 0);
this.camera = new THREE.PerspectiveCamera(85, 1, 0.001, 10000);
this.camera.rotation.order = 'ZYX';
this.camera.up = new THREE.Vector3(0, 0, 1);
// Create scene
@@ -36,6 +36,31 @@ window.WorldRenderer = class {
}
render(partialTicks) {
// Setup camera
this.orientCamera(partialTicks);
// Render chunks
this.renderChunks(partialTicks);
// Render window
this.webRenderer.render(this.scene, this.camera);
}
orientCamera(partialTicks) {
let player = this.minecraft.player;
// Rotation
this.camera.rotation.y = player.yaw * (Math.PI / 180);
this.camera.rotation.x = player.pitch * (Math.PI / 180);
// Position
let x = player.prevX + (player.x - player.prevX) * partialTicks;
let y = player.prevY + (player.y - player.prevY) * partialTicks;
let z = player.prevZ + (player.z - player.prevZ) * partialTicks;
this.camera.position.set(x, y + player.getEyeHeight(), z);
}
renderChunks(partialTicks) {
let world = this.minecraft.world;
const xKeys = Object.keys(world.chunks)
@@ -56,10 +81,5 @@ window.WorldRenderer = class {
}
}
}
// Render window
this.webRenderer.render(this.scene, this.camera);
}
}
@@ -45,7 +45,7 @@ window.ChunkSection = class {
});
let cube = new THREE.Mesh(geometry, material);
cube.position.set(absoluteX - 0.5, absoluteY - 0.5, absoluteZ - 0.5);
cube.position.set(absoluteX + 0.5, absoluteY + 0.5, absoluteZ + 0.5);
this.group.add(cube);
}
+38 -6
View File
@@ -15,6 +15,38 @@ window.World = class {
}
}
getChunkAtBlock(x, y, z) {
let chunk = this.getChunkAt(x >> 4, z >> 4);
return y < 0 || y > World.TOTAL_HEIGHT ? null : chunk.getSection(y >> 4);
}
getCollisionBoxes(aabb) {
let boundingBoxList = [];
let minX = Math.floor(aabb.minX) - 1;
let maxX = Math.ceil(aabb.maxX) + 1;
let minY = Math.floor(aabb.minY) - 1;
let maxY = Math.ceil(aabb.maxY) + 1;
let minZ = Math.floor(aabb.minZ) - 1;
let maxZ = Math.ceil(aabb.maxZ) + 1;
for (let x = minX; x < maxX; x++) {
for (let y = minY; y < maxY; y++) {
for (let z = minZ; z < maxZ; z++) {
if (this.isSolidBlockAt(x, y, z)) {
boundingBoxList.push(new BoundingBox(x, y, z, x + 1, y + 1, z + 1));
}
}
}
}
return boundingBoxList;
}
isSolidBlockAt(x, y, z) {
let typeId = this.getBlockAt(x, y, z);
return typeId !== 0; /* && Block.getById(typeId).isSolid();*/
}
setBlockAt(x, y, z, type) {
let chunkSection = this.getChunkAtBlock(x, y, z);
if (chunkSection != null) {
@@ -24,6 +56,12 @@ window.World = class {
this.blockChanged(x, y, z);
}
getBlockAt(x, y, z) {
let chunkSection = this.getChunkAtBlock(x, y, z);
return chunkSection == null ? 0 : chunkSection.getBlockAt(x & 15, y & 15, z & 15);
}
getChunkAt(x, z) {
let zArray = this.chunks[x];
if (typeof zArray === 'undefined') {
@@ -65,10 +103,4 @@ window.World = class {
}
}
getChunkAtBlock(x, y, z) {
let chunk = this.getChunkAt(x >> 4, z >> 4);
return y < 0 || y > World.TOTAL_HEIGHT ? null : chunk.getSection(y >> 4);
}
}
+265
View File
@@ -0,0 +1,265 @@
window.BoundingBox = class {
/**
* Bounding box
*
* @param minX Minimum x side
* @param minY Minimum y side
* @param minZ Minimum z side
* @param maxX Maximum x side
* @param maxY Maximum y side
* @param maxZ Maximum z side
*/
constructor(minX, minY, minZ, maxX, maxY, maxZ) {
this.epsilon = 0.0;
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
/**
* Copy the current bounding box object
*
* @return Clone of the bounding box
*/
clone() {
return new BoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
}
/**
* Expand the bounding box. Positive and negative numbers controls which side of the box should grow.
*
* @param x Amount to expand the minX or maxX
* @param y Amount to expand the minY or maxY
* @param z Amount to expand the minZ or maxZ
* @return The expanded bounding box
*/
expand(x, y, z) {
let minX = this.minX;
let minY = this.minY;
let minZ = this.minZ;
let maxX = this.maxX;
let maxY = this.maxY;
let maxZ = this.maxZ;
// Handle expanding of min/max x
if (x < 0.0) {
minX += x;
} else {
maxX += x;
}
// Handle expanding of min/max y
if (y < 0.0) {
minY += y;
} else {
maxY += y;
}
// Handle expanding of min/max z
if (z < 0.0) {
minZ += z;
} else {
maxZ += z;
}
// Create new bounding box
return new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Expand the bounding box on both sides.
* The center is always fixed when using grow.
*
* @param x
* @param y
* @param z
* @return
*/
grow(x, y, z) {
return new BoundingBox(
this.minX - x,
this.minY - y,
this.minZ - z,
this.maxX + x,
this.maxY + y,
this.maxZ + z
);
}
/**
* Check for collision on the X axis
*
* @param otherBoundingBox The other bounding box that is colliding with the this one.
* @param x Position on the X axis that is colliding
* @return Returns the corrected x position that collided.
*/
clipXCollide(otherBoundingBox, x) {
// Check if the boxes are colliding on the Y axis
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
return x;
}
// Check if the boxes are colliding on the Z axis
if (otherBoundingBox.maxZ <= this.minZ || otherBoundingBox.minZ >= this.maxZ) {
return x;
}
// Check for collision if the X axis of the current box is bigger
if (x > 0.0 && otherBoundingBox.maxX <= this.minX) {
let max = this.minX - otherBoundingBox.maxX - this.epsilon;
if (max < x) {
x = max;
}
}
// Check for collision if the X axis of the current box is smaller
if (x < 0.0 && otherBoundingBox.minX >= this.maxX) {
let max = this.maxX - otherBoundingBox.minX + this.epsilon;
if (max > x) {
x = max;
}
}
return x;
}
/**
* Check for collision on the Y axis
*
* @param otherBoundingBox The other bounding box that is colliding with the this one.
* @param y Position on the X axis that is colliding
* @return Returns the corrected x position that collided.
*/
clipYCollide(otherBoundingBox, y) {
// Check if the boxes are colliding on the X axis
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
return y;
}
// Check if the boxes are colliding on the Z axis
if (otherBoundingBox.maxZ <= this.minZ || otherBoundingBox.minZ >= this.maxZ) {
return y;
}
// Check for collision if the Y axis of the current box is bigger
if (y > 0.0 && otherBoundingBox.maxY <= this.minY) {
let max = this.minY - otherBoundingBox.maxY - this.epsilon;
if (max < y) {
y = max;
}
}
// Check for collision if the Y axis of the current box is bigger
if (y < 0.0 && otherBoundingBox.minY >= this.maxY) {
let max = this.maxY - otherBoundingBox.minY + this.epsilon;
if (max > y) {
y = max;
}
}
return y;
}
/**
* Check for collision on the Y axis
*
* @param otherBoundingBox The other bounding box that is colliding with the this one.
* @param z Position on the X axis that is colliding
* @return Returns the corrected x position that collided.
*/
clipZCollide(otherBoundingBox, z) {
// Check if the boxes are colliding on the X axis
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
return z;
}
// Check if the boxes are colliding on the Y axis
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
return z;
}
// Check for collision if the Z axis of the current box is bigger
if (z > 0.0 && otherBoundingBox.maxZ <= this.minZ) {
let max = this.minZ - otherBoundingBox.maxZ - this.epsilon;
if (max < z) {
z = max;
}
}
// Check for collision if the Z axis of the current box is bigger
if (z < 0.0 && otherBoundingBox.minZ >= this.maxZ) {
let max = this.maxZ - otherBoundingBox.minZ + this.epsilon;
if (max > z) {
z = max;
}
}
return z;
}
/**
* Check if the two boxes are intersecting/overlapping
*
* @param otherBoundingBox The other bounding box that could intersect
* @return The two boxes are overlapping
*/
intersects(otherBoundingBox) {
// Check on X axis
if (otherBoundingBox.maxX <= this.minX || otherBoundingBox.minX >= this.maxX) {
return false;
}
// Check on Y axis
if (otherBoundingBox.maxY <= this.minY || otherBoundingBox.minY >= this.maxY) {
return false;
}
// Check on Z axis
return (!(otherBoundingBox.maxZ <= this.minZ)) && (!(otherBoundingBox.minZ >= this.maxZ));
}
/**
* Move the bounding box relative.
*
* @param x Relative offset x
* @param y Relative offset y
* @param z Relative offset z
*/
move(x, y, z) {
this.minX += x;
this.minY += y;
this.minZ += z;
this.maxX += x;
this.maxY += y;
this.maxZ += z;
}
/**
* Create a new bounding box with the given offset
*
* @param x Relative offset x
* @param y Relative offset x
* @param z Relative offset x
* @return New bounding box with the given offset relative to this bounding box
*/
offset(x, y, z) {
return new BoundingBox(
this.minX + x,
this.minY + y,
this.minZ + z,
this.maxX + x,
this.maxY + y,
this.maxZ + z
);
}
}
+14
View File
@@ -0,0 +1,14 @@
window.Keyboard = class {
static state = {};
static create() {
window.addEventListener('keyup', (e) => Keyboard.state[e.code] = false);
window.addEventListener('keydown', (e) => Keyboard.state[e.code] = true);
};
static isKeyDown(key) {
return Keyboard.state[key];
}
}
+3
View File
@@ -48,10 +48,13 @@ loadScripts([
// Minecraft Source
"src/net/minecraft/util/Timer.js",
"src/net/minecraft/util/BoundingBox.js",
"src/net/minecraft/util/Keyboard.js",
"src/net/minecraft/client/GameWindow.js",
"src/net/minecraft/client/world/ChunkSection.js",
"src/net/minecraft/client/world/Chunk.js",
"src/net/minecraft/client/world/World.js",
"src/net/minecraft/client/entity/Player.js",
"src/net/minecraft/client/Minecraft.js",
"src/net/minecraft/client/render/WorldRenderer.js"
]).then(() => {