implement font renderer and gui scaling
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
window.FontRenderer = class {
|
||||
|
||||
static BITMAP_SIZE = 16;
|
||||
static FIELD_SIZE = 8;
|
||||
|
||||
static COLOR_CODE_INDEX_LOOKUP = "0123456789abcdef";
|
||||
|
||||
constructor() {
|
||||
this.charWidths = [];
|
||||
|
||||
let scope = this;
|
||||
this.texture = Gui.loadTexture("font.png", function () {
|
||||
let bitMap = scope.createBitMap(scope.texture);
|
||||
|
||||
// Calculate character width
|
||||
for (let i = 0; i < 128; i++) {
|
||||
scope.charWidths[i] = scope.calculateCharacterWidthAt(bitMap, i % FontRenderer.BITMAP_SIZE, Math.floor(i / FontRenderer.BITMAP_SIZE)) + 2;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
calculateCharacterWidthAt(bitMap, indexX, indexY) {
|
||||
// We scan the bitmap field from right to left
|
||||
for (let x = indexX * FontRenderer.FIELD_SIZE + FontRenderer.FIELD_SIZE - 1; x >= indexX * FontRenderer.FIELD_SIZE; x--) {
|
||||
|
||||
// Scan this column from top to bottom
|
||||
for (let y = indexY * FontRenderer.FIELD_SIZE; y < indexY * FontRenderer.FIELD_SIZE + FontRenderer.FIELD_SIZE; y++) {
|
||||
|
||||
let i = (x + y * this.texture.width) * 4;
|
||||
|
||||
let red = bitMap[i];
|
||||
let green = bitMap[i + 1];
|
||||
let blue = bitMap[i + 2];
|
||||
let alpha = bitMap[i + 3];
|
||||
|
||||
// Return width if there is a white pixel
|
||||
if (red !== 0 || green !== 0 || blue !== 0 || alpha !== 0) {
|
||||
return x - indexX * FontRenderer.FIELD_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty field width (Could be a space character)
|
||||
return 2;
|
||||
}
|
||||
|
||||
drawString(stack, string, x, y, color = -1) {
|
||||
this.drawStringRaw(stack, string, x + 1, y + 1, (color & 0xFCFCFC) >> 2, true);
|
||||
this.drawStringRaw(stack, string, x, y, color, false);
|
||||
}
|
||||
|
||||
drawStringRaw(stack, string, x, y, color = -1, isShadow = true) {
|
||||
stack.save();
|
||||
|
||||
if (isShadow) {
|
||||
stack.filter = "brightness(0%)";
|
||||
}
|
||||
|
||||
// For each character
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
let character = string[i];
|
||||
let code = string[i].charCodeAt(0);
|
||||
|
||||
// Handle color codes if character is &
|
||||
if (character === '&' && i !== string.length - 1) {
|
||||
// Get the next character
|
||||
let nextCharacter = string[i + 1];
|
||||
|
||||
// Change color of string
|
||||
//this.setColor(this.getColorOfCharacter(nextCharacter), isShadow);
|
||||
|
||||
// Skip the color code for rendering
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get character offset in bitmap
|
||||
let textureOffsetX = code % FontRenderer.BITMAP_SIZE * FontRenderer.FIELD_SIZE;
|
||||
let textureOffsetY = Math.floor(code / FontRenderer.BITMAP_SIZE) * FontRenderer.FIELD_SIZE;
|
||||
|
||||
// Draw character
|
||||
Gui.drawSprite(
|
||||
stack,
|
||||
this.texture,
|
||||
textureOffsetX, textureOffsetY,
|
||||
FontRenderer.FIELD_SIZE, FontRenderer.FIELD_SIZE,
|
||||
x, y,
|
||||
FontRenderer.FIELD_SIZE, FontRenderer.FIELD_SIZE
|
||||
);
|
||||
|
||||
// Increase drawing cursor
|
||||
x += this.charWidths[code];
|
||||
}
|
||||
|
||||
stack.restore();
|
||||
}
|
||||
|
||||
getColorOfCharacter(character) {
|
||||
let index = FontRenderer.COLOR_CODE_INDEX_LOOKUP.indexOf(character);
|
||||
let brightness = (index & 0x8) * 8;
|
||||
|
||||
// Convert index to RGB
|
||||
let b = (index & 0x1) * 191 + brightness;
|
||||
let g = ((index & 0x2) >> 1) * 191 + brightness;
|
||||
let r = ((index & 0x4) >> 2) * 191 + brightness;
|
||||
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
getStringWidth(string) {
|
||||
let length = 0;
|
||||
|
||||
// For each character
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
|
||||
// Check for color code
|
||||
if (string[i] === '&') {
|
||||
// Skip the next character
|
||||
i++;
|
||||
} else {
|
||||
// Add the width of the character
|
||||
let code = string[i].charCodeAt(0);
|
||||
length += this.charWidths[code];
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
createBitMap(img) {
|
||||
let canvas = document.createElement('canvas');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
|
||||
return canvas.getContext('2d').getImageData(0, 0, img.width, img.height).data;
|
||||
}
|
||||
}
|
||||
|
||||
window.FontRenderer.INSTANCE = new FontRenderer();
|
||||
@@ -7,10 +7,6 @@ window.WorldRenderer = class {
|
||||
this.window = window;
|
||||
this.chunkSectionUpdateQueue = [];
|
||||
|
||||
this.supportWebGL = !!WebGLRenderingContext
|
||||
&& (!!document.createElement('canvas').getContext('experimental-webgl')
|
||||
|| !!document.createElement('canvas').getContext('webgl'));
|
||||
|
||||
// Load terrain
|
||||
this.terrainTexture = new THREE.TextureLoader().load('src/resources/terrain.png');
|
||||
this.terrainTexture.magFilter = THREE.NearestFilter;
|
||||
@@ -41,12 +37,9 @@ window.WorldRenderer = class {
|
||||
this.scene.matrixAutoUpdate = false;
|
||||
|
||||
// Create web renderer
|
||||
this.canvasElement = document.createElement('canvas')
|
||||
this.webRenderer = this.supportWebGL ? new THREE.WebGLRenderer({
|
||||
canvas: this.canvasElement,
|
||||
antialias: false
|
||||
}) : new THREE.CanvasRenderer({
|
||||
canvas: this.canvasElement,
|
||||
this.canvas = document.createElement('canvas')
|
||||
this.webRenderer = new THREE.WebGLRenderer({
|
||||
canvas: this.canvas,
|
||||
antialias: false
|
||||
});
|
||||
|
||||
@@ -70,12 +63,15 @@ window.WorldRenderer = class {
|
||||
|
||||
// Get context stack of 2d canvas
|
||||
this.stack2d = this.canvas2d.getContext('2d');
|
||||
this.stack2d.webkitImageSmoothingEnabled = false;
|
||||
this.stack2d.mozImageSmoothingEnabled = false;
|
||||
this.stack2d.imageSmoothingEnabled = false;
|
||||
|
||||
// Create texture from rendered graphics.
|
||||
this.frameBuffer = new THREE.Texture(this.canvas2d)
|
||||
this.frameBuffer.needsUpdate = true;
|
||||
this.frameBuffer.minFilter = THREE.LinearFilter;
|
||||
this.frameBuffer.maxFilter = THREE.LinearFilter;
|
||||
|
||||
// Create HUD material.
|
||||
let material = new THREE.MeshBasicMaterial({
|
||||
|
||||
Reference in New Issue
Block a user