implement ingame menu
This commit is contained in:
@@ -28,8 +28,23 @@ window.GameWindow = class {
|
||||
// Mouse motion
|
||||
document.addEventListener('mousemove', event => this.onMouseMove(event), false);
|
||||
|
||||
// Losing focus event
|
||||
window.addEventListener("mouseout", function () {
|
||||
if (minecraft.currentScreen === null) {
|
||||
minecraft.displayScreen(new GuiIngameMenu());
|
||||
}
|
||||
});
|
||||
|
||||
// Mouse buttons
|
||||
document.addEventListener('click', event => minecraft.onMouseClicked(event.button), false);
|
||||
document.addEventListener('click', function (event) {
|
||||
// Handle in-game mouse click
|
||||
minecraft.onMouseClicked(event.button);
|
||||
|
||||
// Handle mouse click on screen
|
||||
if (!(minecraft.currentScreen === null)) {
|
||||
minecraft.currentScreen.mouseClicked(event.x, event.y, event.code);
|
||||
}
|
||||
}, false);
|
||||
|
||||
// Keyboard interaction with screen
|
||||
window.addEventListener('keydown', function (event) {
|
||||
@@ -41,6 +56,9 @@ window.GameWindow = class {
|
||||
// Cancel browser interaction
|
||||
event.preventDefault();
|
||||
}
|
||||
} else if (event.code === 'Escape') {
|
||||
event.preventDefault();
|
||||
minecraft.displayScreen(new GuiIngameMenu());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,7 +67,12 @@ window.GameWindow = class {
|
||||
}
|
||||
|
||||
requestFocus() {
|
||||
this.renderer.canvasElement.requestPointerLock();
|
||||
let scope = this;
|
||||
|
||||
setTimeout(function () {
|
||||
window.focus();
|
||||
scope.renderer.canvasElement.requestPointerLock();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
loadRenderer(renderer) {
|
||||
@@ -64,10 +87,10 @@ window.GameWindow = class {
|
||||
this.onResize();
|
||||
|
||||
// Request focus
|
||||
let minecraft = this.minecraft;
|
||||
let scope = this;
|
||||
canvas.onclick = function () {
|
||||
if (minecraft.currentScreen === null) {
|
||||
canvas.requestPointerLock();
|
||||
if (scope.minecraft.currentScreen === null) {
|
||||
scope.requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,14 +113,13 @@ window.GameWindow = class {
|
||||
|
||||
// Reinitialize current screen
|
||||
if (!(this.minecraft.currentScreen === null)) {
|
||||
this.minecraft.currentScreen.init(this.minecraft, this.width, this.height);
|
||||
this.minecraft.currentScreen.setup(this.minecraft, this.width, this.height);
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged() {
|
||||
this.mouseLocked = document.pointerLockElement === this.renderer.canvasElement;
|
||||
|
||||
// Open in-game menu
|
||||
if (!this.mouseLocked && this.minecraft.currentScreen === null) {
|
||||
this.minecraft.displayScreen(new GuiIngameMenu());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ window.Minecraft = class {
|
||||
this.worldRenderer.scene.add(this.world.group);
|
||||
|
||||
// Create player
|
||||
this.player = new Player(this.world);
|
||||
this.player = new Player(this, this.world);
|
||||
this.pickedBlock = 1;
|
||||
|
||||
// Initialize
|
||||
@@ -48,6 +48,10 @@ window.Minecraft = class {
|
||||
this.requestNextFrame();
|
||||
}
|
||||
|
||||
hasInGameFocus() {
|
||||
return this.window.mouseLocked && this.currentScreen === null;
|
||||
}
|
||||
|
||||
requestNextFrame() {
|
||||
let scope = this;
|
||||
requestAnimationFrame(function () {
|
||||
@@ -88,7 +92,7 @@ window.Minecraft = class {
|
||||
|
||||
onRender(partialTicks) {
|
||||
// Player rotation
|
||||
if (this.window.mouseLocked && !(this.currentScreen === "null")) {
|
||||
if (this.hasInGameFocus()) {
|
||||
this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY);
|
||||
|
||||
this.window.mouseMotionX = 0;
|
||||
@@ -112,7 +116,7 @@ window.Minecraft = class {
|
||||
if (screen === null) {
|
||||
this.window.requestFocus();
|
||||
} else {
|
||||
screen.init(this, this.window.width, this.window.height);
|
||||
screen.setup(this, this.window.width, this.window.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
window.Player = class {
|
||||
|
||||
constructor(world) {
|
||||
constructor(minecraft, world) {
|
||||
this.minecraft = minecraft;
|
||||
this.world = world;
|
||||
|
||||
this.prevX = 0;
|
||||
@@ -309,38 +310,40 @@ window.Player = class {
|
||||
let jumping = false;
|
||||
let sneaking = false;
|
||||
|
||||
if (Keyboard.isKeyDown("KeyR")) { // R
|
||||
this.respawn();
|
||||
}
|
||||
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 (this.minecraft.hasInGameFocus()) {
|
||||
if (Keyboard.isKeyDown("KeyR")) { // R
|
||||
this.respawn();
|
||||
}
|
||||
}
|
||||
if (Keyboard.isKeyDown("KeyQ")) { // Q
|
||||
sneaking = true;
|
||||
}
|
||||
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;
|
||||
|
||||
if (sneaking) {
|
||||
moveStrafe = moveStrafe * 0.3;
|
||||
moveForward = moveForward * 0.3;
|
||||
this.updateFOVModifier();
|
||||
}
|
||||
}
|
||||
if (Keyboard.isKeyDown("KeyQ")) { // Q
|
||||
sneaking = true;
|
||||
}
|
||||
|
||||
if (sneaking) {
|
||||
moveStrafe = moveStrafe * 0.3;
|
||||
moveForward = moveForward * 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
this.moveForward = moveForward;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
window.Gui = class {
|
||||
|
||||
static FONT = "normal 20px Minecraftia";
|
||||
|
||||
drawRect(stack, left, top, right, bottom, color, alpha = 1) {
|
||||
stack.save();
|
||||
stack.fillStyle = color;
|
||||
@@ -8,18 +10,28 @@ window.Gui = class {
|
||||
stack.restore();
|
||||
}
|
||||
|
||||
drawString(stack, string, x, y, color) {
|
||||
this._drawString(stack, string, x, y, color, 0, false);
|
||||
drawCenteredString(stack, string, x, y, color = 'white') {
|
||||
this._drawString(stack, string, x + this.getStringWidth(stack, string) / 2, y, color, 1);
|
||||
}
|
||||
|
||||
_drawString(stack, string, x, y, color, alignment, bold) {
|
||||
let size = 24;
|
||||
stack.font = (bold ? "bold" : "normal") + " " + size + "px Minecraftia";
|
||||
stack.fillStyle = color;
|
||||
drawString(stack, string, x, y, color = 'white') {
|
||||
this._drawString(stack, string, x, y, color, 0);
|
||||
}
|
||||
|
||||
_drawString(stack, string, x, y, color, alignment) {
|
||||
stack.font = Gui.FONT;
|
||||
stack.fillStyle = 'black';
|
||||
stack.textAlign = alignment === 0 ? "center" : alignment < 0 ? "left" : "right";
|
||||
stack.fillText(string, x + 2, y + 2);
|
||||
stack.fillStyle = color;
|
||||
stack.fillText(string, x, y);
|
||||
}
|
||||
|
||||
getStringWidth(stack, string) {
|
||||
stack.font = Gui.FONT;
|
||||
return stack.measureText(string).width;
|
||||
}
|
||||
|
||||
drawTexture(stack, texture, x, y, width, height, alpha = 1.0) {
|
||||
this.drawSprite(stack, texture, 0, 0, 256, 256, x, y, width, height, alpha);
|
||||
}
|
||||
@@ -42,7 +54,7 @@ window.Gui = class {
|
||||
stack.restore();
|
||||
}
|
||||
|
||||
loadTexture(path) {
|
||||
static loadTexture(path) {
|
||||
let img = new Image();
|
||||
img.src = path;
|
||||
return img;
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
window.GuiScreen = class extends Gui {
|
||||
|
||||
init(minecraft, width, height) {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.buttonList = [];
|
||||
}
|
||||
|
||||
setup(minecraft, width, height) {
|
||||
this.minecraft = minecraft;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.buttonList = [];
|
||||
}
|
||||
|
||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||
|
||||
for (let i in this.buttonList) {
|
||||
let button = this.buttonList[i];
|
||||
button.render(stack, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
keyTyped(code) {
|
||||
@@ -18,4 +33,14 @@ window.GuiScreen = class extends Gui {
|
||||
return false;
|
||||
}
|
||||
|
||||
mouseClicked(mouseX, mouseY, mouseButton) {
|
||||
for (let i in this.buttonList) {
|
||||
let button = this.buttonList[i];
|
||||
|
||||
if (button.isMouseOver(mouseX, mouseY)) {
|
||||
button.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ window.IngameOverlay = class extends Gui {
|
||||
super();
|
||||
this.window = window;
|
||||
|
||||
this.textureCrosshair = this.loadTexture("icons.png");
|
||||
this.textureCrosshair = Gui.loadTexture("icons.png");
|
||||
}
|
||||
|
||||
render(stack, mouseX, mouseY, partialTicks) {
|
||||
|
||||
@@ -4,8 +4,23 @@ window.GuiIngameMenu = class extends GuiScreen {
|
||||
super();
|
||||
}
|
||||
|
||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||
init() {
|
||||
super.init();
|
||||
|
||||
let scope = this;
|
||||
this.buttonList.push(new GuiButton("Back to game", this.width / 2 - 100 * 3, this.height / 2 - 50 * 3, 200 * 3, 20 * 3, function () {
|
||||
scope.minecraft.displayScreen(null);
|
||||
}));
|
||||
}
|
||||
|
||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||
// Background
|
||||
this.drawRect(stack, 0, 0, this.width, this.height, 'black', 0.6);
|
||||
|
||||
// Title
|
||||
this.drawCenteredString(stack, "Game paused", this.width / 2, 100);
|
||||
|
||||
super.drawScreen(stack, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ window.GuiLoadingScreen = class extends GuiScreen {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.textureBackground = this.loadTexture("background.png");
|
||||
this.textureBackground = Gui.loadTexture("background.png");
|
||||
}
|
||||
|
||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||
@@ -35,6 +35,8 @@ window.GuiLoadingScreen = class extends GuiScreen {
|
||||
this.height / 2 + progressHeight / 2,
|
||||
'#80ff80',
|
||||
);
|
||||
|
||||
super.drawScreen(stack, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
setTitle(title) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
window.GuiButton = class extends Gui {
|
||||
|
||||
static textureGui = Gui.loadTexture("gui.png");
|
||||
|
||||
constructor(string, x, y, width, height, callback) {
|
||||
super();
|
||||
|
||||
this.string = string;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
render(stack, mouseX, mouseY, partialTicks) {
|
||||
let mouseOver = this.isMouseOver(mouseX, mouseY);
|
||||
this.drawSprite(stack, GuiButton.textureGui, 0, mouseOver ? 40 : 20, 200, 20, this.x, this.y, this.width, this.height);
|
||||
this.drawCenteredString(stack, this.string, this.x + this.width / 2, this.y + this.height / 2 + 17);
|
||||
}
|
||||
|
||||
mouseClicked(mouseX, mouseY, mouseButton) {
|
||||
this.callback();
|
||||
}
|
||||
|
||||
isMouseOver(mouseX, mouseY) {
|
||||
return mouseX > this.x && mouseX < this.x + this.width && mouseY > this.y && mouseY < this.y + this.height;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,16 @@ window.World = class {
|
||||
|
||||
// Load world
|
||||
this.generator = new WorldGenerator(this, Date.now() % 100000);
|
||||
|
||||
// Update lights async
|
||||
let scope = this;
|
||||
setInterval(function () {
|
||||
let i = 1000;
|
||||
while (scope.lightUpdateQueue.length >= 10 && i > 0) {
|
||||
i--;
|
||||
scope.lightUpdateQueue.shift().updateBlockLightning(scope);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
onTick() {
|
||||
@@ -83,22 +93,7 @@ window.World = class {
|
||||
updateLights() {
|
||||
let scope = this;
|
||||
|
||||
if (this.lightUpdateQueue.length > 10) {
|
||||
// Update lights async
|
||||
setTimeout(function () {
|
||||
// Update lights in queue
|
||||
let i = 5000;
|
||||
while (scope.lightUpdateQueue.length > 0) {
|
||||
if (i <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
let meta = scope.lightUpdateQueue.shift();
|
||||
meta.updateBlockLightning(scope);
|
||||
i--;
|
||||
}
|
||||
}, 0);
|
||||
} else {
|
||||
if (this.lightUpdateQueue.length < 10) {
|
||||
// Update lights in queue
|
||||
let i = 10;
|
||||
while (scope.lightUpdateQueue.length > 0) {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.4 KiB |
@@ -61,6 +61,7 @@ loadScripts([
|
||||
"src/js/net/minecraft/util/Keyboard.js",
|
||||
"src/js/net/minecraft/client/gui/Gui.js",
|
||||
"src/js/net/minecraft/client/gui/GuiScreen.js",
|
||||
"src/js/net/minecraft/client/gui/widgets/GuiButton.js",
|
||||
"src/js/net/minecraft/client/gui/IngameOverlay.js",
|
||||
"src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js",
|
||||
"src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js",
|
||||
|
||||
Reference in New Issue
Block a user