Skip to content

Commit

Permalink
Use Canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenwaterman committed Jan 31, 2020
1 parent 33efa2d commit 3406983
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 142 deletions.
112 changes: 14 additions & 98 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,104 +1,20 @@
<script>
import Cell from "./Cell.svelte";
import { width, height, cellCount, regenerate } from "./cellsStore.js";
$: rows = Array($height)
.fill(null)
.map((_, y) =>
Array($width)
.fill(null)
.map((_, x) => x + y * $width)
);
function createSections(
sectionsWide,
defaultSectionWidth,
finalSectionWidth,
sectionsTall,
defaultSectionHeight,
finalSectionHeight,
boardWidth
) {
const sections = [];
for (let sectionY = 0; sectionY < sectionsTall; sectionY++) {
for (let sectionX = 0; sectionX < sectionsWide; sectionX++) {
const height =
sectionY === sectionsTall - 1
? finalSectionHeight
: defaultSectionHeight;
const width =
sectionX === sectionsWide - 1
? finalSectionWidth
: defaultSectionWidth;
const firstIndex =
sectionY * defaultSectionHeight * boardWidth +
sectionX * defaultSectionWidth;
const indices = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const offset = x + y * boardWidth;
indices.push(firstIndex + offset);
}
}
sections.push({
x: sectionX,
y: sectionY,
width,
height,
indices
});
}
}
return sections;
}
$: cellsPerSectionTarget = Math.max(20, $cellCount / 100);
$: sectionSize = Math.round(Math.sqrt(cellsPerSectionTarget));
$: sectionsWide = Math.ceil($width / sectionSize);
$: sectionsTall = Math.ceil($height / sectionSize);
$: finalSectionWidth = $width - (sectionsWide - 1) * sectionSize;
$: finalSectionHeight = $height - (sectionsTall - 1) * sectionSize;
$: sections = createSections(
sectionsWide,
sectionSize,
finalSectionWidth,
sectionsTall,
sectionSize,
finalSectionHeight,
$width
);
import {
height,
width,
cellCount,
canvasStore,
cellSize
} from "./cellsStore.js";
</script>

<style>
.sectionGrid {
display: grid;
grid-gap: 0px;
}
.boardSection {
display: grid;
grid-gap: 0px;
-webkit-backface-visibility: hidden;
backface-visibility: hidden
}
</style>

<main>
<div
class="sectionGrid"
style="grid-template-columns: repeat({sectionsWide}, {sectionSize * 8}px);
grid-template-rows: repeat({sectionsTall}, {sectionSize * 8}px)">
{#each sections as section}
<div
class="boardSection"
style="grid-template-columns: repeat({section.width}, 8px);
grid-template-rows: repeat({section.height}, 8px)">
{#each section.indices as idx}
<Cell index={idx} />
{/each}
</div>
{/each}
</div>
<canvas
bind:this={$canvasStore}
width={$width * $cellSize}
height={$height * $cellSize} />
{#each Array($cellCount).fill(null) as _, idx}
<Cell index={idx} />
{/each}
</main>
117 changes: 74 additions & 43 deletions src/Cell.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<script>
import { cellStores, surroundingStores, width } from "./cellsStore";
import {
cellStores,
surroundingStores,
width,
height,
cellSize,
canvasStore
} from "./cellsStore";
export let index;
$: me = cellStores[index];
Expand All @@ -21,55 +28,79 @@
$: if (clearable) setTimeout(() => surroundings.reveal(), 0);
$: if (flaggable) setTimeout(() => surroundings.reveal(), 0);
let textColor;
$: if (!stateKnown) {
textColor = "transparent";
} else if (isMine) {
textColor = "white";
} else {
textColor = [
"transparent",
"blue",
"green",
"red",
"purple",
"maroon",
"#0aa",
"black",
"#444"
][adjacentMinesCount];
}
$: x = Math.floor(index / $width);
$: x = Math.floor(index / $width);
$: y = index % $width;
$: rectanglePixelX = x * $cellSize;
$: rectanglePixelY = y * $cellSize;
$: textPixelX = rectanglePixelX + $cellSize / 2;
$: textPixelY = rectanglePixelY + $cellSize / 2;
$: light = (x + y) % 2 === 0;
$: text = isMine ? "X" : adjacentMinesCount;
$: textColor = isMine
? "white"
: [
"transparent",
"blue",
"green",
"red",
"purple",
"maroon",
"#0aa",
"black",
"#444"
][adjacentMinesCount];
function getBackgroundColor(stateKnown, isMine, light) {
if (stateKnown && isMine) return "#f55";
if (stateKnown && isMine && light) return "#f55";
if (stateKnown && isMine && !light) return "#d33";
if (stateKnown && !isMine && light) return "#fff";
if (stateKnown && !isMine && !light) return "#ddd";
if (stateKnown && !isMine && !light) return "#ccc";
if (!stateKnown && light) return "#aaa";
if (!stateKnown && !light) return "#999";
if (!stateKnown && !light) return "#777";
}
$: backgroundColor = getBackgroundColor(stateKnown, isMine, light);
$: cellText = isMine ? "X" : adjacentMinesCount;
</script>
$: backgroundColor = getBackgroundColor(stateKnown, isMine, light);
<style>
.cell {
display: flex;
align-items: center;
justify-content: center;
font-size: 5pt;
font-weight: 700;
height: 8px;
width: 8px;
function drawCell(
ctx,
rectanglePixelX,
rectanglePixelY,
textPixelX,
textPixelY,
size,
stateKnown,
text,
textColor,
backgroundColor
) {
if (ctx === null) return;
ctx.beginPath();
ctx.fillStyle = backgroundColor;
ctx.rect(rectanglePixelX, rectanglePixelY, size, size);
ctx.fill();
if (stateKnown) {
ctx.fillStyle = textColor;
ctx.fillText(text, textPixelX, textPixelY);
}
}
</style>
<div
class="cell"
style="color: {textColor}; background-color: {backgroundColor}">
{cellText}
</div>
$: ctx = $canvasStore === null ? null : $canvasStore.getContext("2d");
$: if(ctx != null) ctx.font = $cellSize - 1 + "px arial";
$: if(ctx != null) ctx.textAlign = "center";
$: if(ctx != null) ctx.textBaseline = "middle";
$: drawCell(
ctx,
rectanglePixelX,
rectanglePixelY,
textPixelX,
textPixelY,
$cellSize,
stateKnown,
text,
textColor,
backgroundColor
);
</script>
5 changes: 4 additions & 1 deletion src/cellsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ function generateCells(cellCount) {

return shuffle([...clearCells, ...knownCells, ...mineCells]);
}

export const canvasStore = writable(null);
export const width = writable(100);
export const height = writable(100);
export const cellSize = derived([width, height], ([$width, $height]) =>
Math.floor(800 / Math.max($width, $height))
);
export const cellCount = derived(
[width, height],
([$width, $height]) => $width * $height
Expand Down

0 comments on commit 3406983

Please sign in to comment.