parent
0e9c1816c7
commit
6adc3de1c4
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "minesweeper",
|
||||
"version": "0.80.0",
|
||||
"version": "0.80.1",
|
||||
"description": "Just Minesweeper!",
|
||||
"author": "Felix W. Dekker",
|
||||
"browser": "dist/bundle.js",
|
||||
|
|
|
@ -151,6 +151,6 @@
|
|||
|
||||
<!-- Scripts -->
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script src="bundle.js"></script>
|
||||
<script src="bundle.js?v=%%VERSION_NUMBER%%"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -54,10 +54,12 @@ export function range(length: number, beginAt: number = 0): number[] {
|
|||
*
|
||||
* Taken from https://stackoverflow.com/a/35572620/ (CC BY-SA 3.0).
|
||||
*
|
||||
* @param callback the function to invoke once the font has loaded
|
||||
* @param onSuccess the function to invoke once the font has loaded
|
||||
* @param onFailure the function to invoke if the font cannot be loaded
|
||||
* @param timeout the maximum time in milliseconds to wait for the font to load
|
||||
*/
|
||||
export function waitForForkAwesome(callback: () => void, timeout: number | undefined = undefined): void {
|
||||
export function waitForForkAwesome(onSuccess: () => void, onFailure: () => void,
|
||||
timeout: number | undefined = undefined): void {
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
const fontSize = 36;
|
||||
|
@ -81,9 +83,9 @@ export function waitForForkAwesome(callback: () => void, timeout: number | undef
|
|||
*/
|
||||
function fontOnload(time: number): void {
|
||||
const currentCount = getPixelCount();
|
||||
if (failTime !== undefined && time > failTime) alert(`ForkAwesome failed to load after ${timeout}ms.`);
|
||||
if (failTime !== undefined && time > failTime) onFailure();
|
||||
else if (currentCount < targetPixelCount) requestAnimationFrame(fontOnload);
|
||||
else callback();
|
||||
else onSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,7 +10,9 @@ import {Field, Square} from "./Field";
|
|||
export class Display {
|
||||
private readonly scale: number = 30;
|
||||
private readonly minSquareWidth: number = 6;
|
||||
|
||||
private readonly canvas: HTMLCanvasElement;
|
||||
private readonly font: IconFont;
|
||||
|
||||
private field: Field | null = null;
|
||||
private winTime: number | null = null;
|
||||
|
@ -22,8 +24,8 @@ export class Display {
|
|||
|
||||
private coverSymbol: HTMLCanvasElement | undefined;
|
||||
private flagSymbol: HTMLCanvasElement | undefined;
|
||||
private mineSymbol: HTMLCanvasElement | undefined;
|
||||
private uncoveredMineSymbol: HTMLCanvasElement | undefined;
|
||||
private mineSymbol: HTMLCanvasElement | undefined;
|
||||
private digitSymbols: HTMLCanvasElement[] | undefined;
|
||||
private clockSymbol: HTMLCanvasElement | undefined;
|
||||
private deathsSymbolA: HTMLCanvasElement | undefined;
|
||||
|
@ -35,9 +37,12 @@ export class Display {
|
|||
*
|
||||
* @param canvas the canvas to draw the field in
|
||||
* @param field the field to draw
|
||||
* @param font the font to draw symbols with
|
||||
*/
|
||||
constructor(canvas: HTMLCanvasElement, field: Field | null) {
|
||||
constructor(canvas: HTMLCanvasElement, field: Field | null, font: IconFont = new BasicIconFont()) {
|
||||
this.canvas = canvas;
|
||||
this.font = font;
|
||||
|
||||
this.setField(field);
|
||||
}
|
||||
|
||||
|
@ -58,7 +63,7 @@ export class Display {
|
|||
ctx.font = `${Math.floor(this.scale * 0.55)}px ${font}`;
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(text, Math.floor(this.scale / 2), Math.floor(this.scale / 2));
|
||||
ctx.fillText(text, Math.floor(this.scale / 2), Math.floor(this.scale / 2), this.scale);
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
|
@ -67,17 +72,17 @@ export class Display {
|
|||
|
||||
this.flagSymbol = createCanvas(this.scale, this.scale);
|
||||
ctx = this.flagSymbol.getContext("2d")!;
|
||||
fillText("\uf024", "ForkAwesome", "#f00");
|
||||
|
||||
this.mineSymbol = createCanvas(this.scale, this.scale);
|
||||
ctx = this.mineSymbol.getContext("2d")!;
|
||||
fillText("\uf1e2", "ForkAwesome", "#00007b");
|
||||
fillText(this.font.flag, this.font.fontFace, "#f00");
|
||||
|
||||
this.uncoveredMineSymbol = createCanvas(this.scale, this.scale);
|
||||
ctx = this.uncoveredMineSymbol.getContext("2d")!;
|
||||
ctx.fillStyle = "#f00";
|
||||
ctx.fillRect(1, 1, this.scale - 2, this.scale - 2);
|
||||
fillText("\uf1e2", "ForkAwesome", "#000");
|
||||
fillText(this.font.uncoveredMine, this.font.fontFace, "#000");
|
||||
|
||||
this.mineSymbol = createCanvas(this.scale, this.scale);
|
||||
ctx = this.mineSymbol.getContext("2d")!;
|
||||
fillText(this.font.mine, this.font.fontFace, "#00007b");
|
||||
|
||||
const digitColors =
|
||||
["", "#0000ff", "#007b00", "#ff0000", "#00007b", "#7b0000", "#007b7b", "#000000", "#7b7b7b"];
|
||||
|
@ -90,15 +95,15 @@ export class Display {
|
|||
|
||||
this.clockSymbol = createCanvas(this.scale, this.scale);
|
||||
ctx = this.clockSymbol.getContext("2d")!;
|
||||
fillText("\uf017", "ForkAwesome");
|
||||
fillText(this.font.clock, this.font.fontFace);
|
||||
|
||||
this.deathsSymbolA = createCanvas(this.scale, this.scale);
|
||||
ctx = this.deathsSymbolA.getContext("2d")!;
|
||||
fillText("\uf0f9", "ForkAwesome", "#fff");
|
||||
fillText(this.font.deaths, this.font.fontFace, "#fff");
|
||||
|
||||
this.deathsSymbolB = createCanvas(this.scale, this.scale);
|
||||
ctx = this.deathsSymbolB.getContext("2d")!;
|
||||
fillText("\uf0f9", "ForkAwesome", "#f00");
|
||||
fillText(this.font.deaths, this.font.fontFace, "#f00");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,3 +429,43 @@ export class Display {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A font that can be used to display icons for the display.
|
||||
*/
|
||||
export interface IconFont {
|
||||
fontFace: string;
|
||||
|
||||
flag: string;
|
||||
uncoveredMine: string;
|
||||
mine: string;
|
||||
clock: string;
|
||||
deaths: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic font that can be displayed in any browser.
|
||||
*/
|
||||
export class BasicIconFont implements IconFont {
|
||||
fontFace = "Courier New";
|
||||
|
||||
flag = "F";
|
||||
uncoveredMine = "X";
|
||||
mine = "Mines";
|
||||
clock = "Time";
|
||||
deaths = "Deaths";
|
||||
}
|
||||
|
||||
/**
|
||||
* ForkAwesome, which can be used on any browser that does not block external fonts.
|
||||
*/
|
||||
export class ForkAwesomeFont implements IconFont {
|
||||
fontFace = "ForkAwesome";
|
||||
|
||||
flag = "\uf024";
|
||||
uncoveredMine = "\uf1e2";
|
||||
mine = "\uf1e2";
|
||||
clock = "\uf017";
|
||||
deaths = "\uf0f9";
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import {$} from "@fwdekker/template";
|
|||
import alea from "alea";
|
||||
import {stringToHash} from "./Common";
|
||||
import {customDifficulty, defaultDifficulty, difficulties} from "./Difficulty";
|
||||
import {Display} from "./Display";
|
||||
import {BasicIconFont, Display, ForkAwesomeFont} from "./Display";
|
||||
import {Field} from "./Field";
|
||||
import {Solver} from "./Solver";
|
||||
import {LocalStatistics} from "./Statistics";
|
||||
|
@ -51,12 +51,15 @@ export class Game {
|
|||
|
||||
/**
|
||||
* Constructs and starts a new game of Minesweeper.
|
||||
*
|
||||
* @param withForkAwesome whether ForkAwesome can be used
|
||||
*/
|
||||
constructor() {
|
||||
constructor(withForkAwesome: boolean = true) {
|
||||
this.canvas = $("#canvas");
|
||||
|
||||
this.field = null; // Placeholder until `initNewField`
|
||||
this.display = new Display(this.canvas, this.field);
|
||||
this.display =
|
||||
new Display(this.canvas, this.field, withForkAwesome ? new ForkAwesomeFont() : new BasicIconFont());
|
||||
this.display.startDrawLoop();
|
||||
this.canvas.style.visibility = "unset";
|
||||
|
||||
|
|
|
@ -23,5 +23,12 @@ doAfterLoad(() => {
|
|||
|
||||
|
||||
// Start game
|
||||
waitForForkAwesome(() => new Game(), 3000);
|
||||
waitForForkAwesome(
|
||||
() => new Game(),
|
||||
() => {
|
||||
alert("External font could not be loaded. Using fallback font. Is a browser extension blocking fonts?");
|
||||
new Game(false);
|
||||
},
|
||||
3000
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue