-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
537 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,147 +1,36 @@ | ||
<script lang="ts"> | ||
import { WorldRenderer } from "$lib/game/Renderer"; | ||
import { load, save } from "$lib/game/Save"; | ||
import { World } from "$lib/game/World"; | ||
import { resize } from "$lib/actions/Resize"; | ||
import { onMount, onDestroy } from "svelte"; | ||
import { createEventDispatcher } from "svelte"; | ||
const dispatcher = createEventDispatcher(); | ||
import Renderer from "./Renderer.svelte"; | ||
export let saveSlot: string; | ||
export let debugNumFrames: number = 0; | ||
export let debugFrameTime: number = 0; | ||
let canvas: HTMLCanvasElement; | ||
let firstCanvasResize: boolean = true; | ||
let world: World; | ||
let renderer: WorldRenderer; | ||
$: if(world) dispatcher('worldChange', world); | ||
$: if(renderer) dispatcher('rendererChange', renderer); | ||
let needsRerender: boolean = false; | ||
let animFrame: number = -1; | ||
const render = () => { | ||
cancelAnimationFrame(animFrame); | ||
animFrame = requestAnimationFrame(render); | ||
if(needsRerender) { | ||
needsRerender = false; | ||
debugNumFrames++; | ||
const start = performance.now(); | ||
renderer.render(); | ||
debugFrameTime = performance.now() - start; | ||
} | ||
} | ||
let keys: Set<string> = new Set(); | ||
let keysInterval: number = -1; | ||
onMount(async () => { | ||
world = load(saveSlot); | ||
renderer = new WorldRenderer(world, canvas); | ||
// TODO: Clean Up! | ||
clearInterval(keysInterval); | ||
keysInterval = setInterval(() => { | ||
let change: boolean = false; | ||
if(keys.has('[')) { | ||
if(renderer.cameraZoom != renderer.cameraScale(1.04)) { | ||
change = true; | ||
} | ||
} | ||
if(keys.has(']')) { | ||
if(renderer.cameraZoom != renderer.cameraScale(0.96)) { | ||
change = true; | ||
} | ||
} | ||
if(keys.has('ArrowUp')) { renderer.cameraTranslate(0, 10); change = true; } | ||
if(keys.has('ArrowDown')) { renderer.cameraTranslate(0, -10); change = true; } | ||
if(keys.has('ArrowLeft')) { renderer.cameraTranslate(10, 0); change = true; } | ||
if(keys.has('ArrowRight')) { renderer.cameraTranslate(-10, 0); change = true; } | ||
if(change) { | ||
needsRerender = true; | ||
} | ||
}, 1000 / 60); | ||
// FIXME: Why is this not always accurate. | ||
// Sometimes renderer.init() does not load theme fully before returning. | ||
await renderer.init(); | ||
setTimeout(() => { | ||
render(); | ||
}, 100); | ||
}); | ||
onDestroy(() => { | ||
cancelAnimationFrame(animFrame); | ||
clearInterval(keysInterval); | ||
save(saveSlot, world); | ||
}); | ||
</script> | ||
|
||
<svelte:window | ||
on:keydown={ev => { | ||
keys.add(ev.key); | ||
}} | ||
on:keyup={ev => { | ||
keys.delete(ev.key); | ||
}} | ||
on:beforeunload={() => { | ||
save(saveSlot, world); | ||
}} | ||
/> | ||
|
||
<canvas | ||
class="w-full h-full cursor-pointer" | ||
bind:this={canvas} | ||
use:resize={(width, height) => { | ||
canvas.width = width; | ||
canvas.height = height; | ||
renderer.cameraScale(1); | ||
if(firstCanvasResize) { | ||
renderer.cameraTranslate(canvas.width / 2, canvas.height / 2); | ||
firstCanvasResize = false; | ||
} | ||
needsRerender = true; | ||
}} | ||
on:mousedown={ev => { | ||
if(document.pointerLockElement == canvas) return; | ||
if(ev.button == 1) { | ||
canvas.requestPointerLock(); | ||
ev.preventDefault(); | ||
} else if(ev.button == 0) { | ||
ev.preventDefault(); | ||
const pos = renderer.cameraPos(ev.offsetX, ev.offsetY); | ||
world.reveal(pos.x, pos.y); | ||
needsRerender = true; | ||
} else if(ev.button == 2) { | ||
ev.preventDefault(); | ||
const pos = renderer.cameraPos(ev.offsetX, ev.offsetY); | ||
world.flag(pos.x, pos.y); | ||
needsRerender = true; | ||
{#if world} | ||
<Renderer {world} on:action={ev => { | ||
if(ev.detail.type == 'reveal') { | ||
world.reveal(ev.detail.pos.x, ev.detail.pos.y); | ||
} else if(ev.detail.type == 'flag') { | ||
world.flag(ev.detail.pos.x, ev.detail.pos.y); | ||
} else if(ev.detail.type == 'reset') { | ||
world.reset(ev.detail.pos.x, ev.detail.pos.y); | ||
} | ||
}} | ||
on:mouseup={ev => { | ||
if(document.pointerLockElement != canvas) return; | ||
if(ev.button != 1) return; | ||
document.exitPointerLock(); | ||
}} | ||
on:mousemove={ev => { | ||
if(document.pointerLockElement != canvas) return; | ||
renderer.cameraTranslate(ev.movementX, ev.movementY); | ||
needsRerender = true; | ||
}} | ||
on:wheel|passive={ev => { | ||
const scale = ev.deltaY > 0 ? 0.9 : 1.1; | ||
if(renderer.cameraZoom != renderer.cameraScale(scale)) { | ||
needsRerender = true; | ||
} | ||
}} | ||
on:contextmenu={ev => { | ||
ev.preventDefault(); | ||
}} | ||
/> | ||
}} /> | ||
{/if} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<!-- https://tholman.com/github-corners/ --> | ||
<script lang="ts"> | ||
export let animation: boolean = true; | ||
export let url: string; | ||
export let newTab: boolean = false; | ||
export let colorBg: string = '#151513'; | ||
export let colorCat: string = '#FFF'; | ||
</script> | ||
|
||
{#if animation} | ||
<style lang="scss"> | ||
.github-corner:hover .octo-arm { | ||
animation: octocat-wave 560ms ease-in-out; | ||
} | ||
@keyframes octocat-wave { | ||
0%, 100% { | ||
transform: rotate(0); | ||
} | ||
20%, 60% { | ||
transform: rotate(-25deg); | ||
} | ||
40%, 80% { | ||
transform: rotate(10deg); | ||
} | ||
} | ||
</style> | ||
{/if} | ||
|
||
<a href={url} target={newTab ? "_blank" : "_self"} class="github-corner" aria-label="View source on GitHub" title="View source on GitHub"> | ||
<svg width="80" height="80" viewBox="0 0 250 250" class="absolute top-0 border-0 right-0 z-[9999]" style:color={colorCat} style:fill={colorBg} aria-hidden="true"> | ||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" /> | ||
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm" /> | ||
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body" /> | ||
</svg> | ||
</a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<script lang="ts"> | ||
import type { ArrayElement } from "$lib/Util"; | ||
import InfoModalBiomes from "./InfoModalBiomes.svelte"; | ||
const tabNames = [ 'Information', 'Biomes', 'Controls' ] as const; | ||
let currentTab: ArrayElement<typeof tabNames> = 'Information'; | ||
</script> | ||
|
||
<style lang="scss"> | ||
.tab { | ||
@apply bg-white bg-opacity-0 transition-colors; | ||
&:hover { | ||
@apply bg-opacity-50; | ||
} | ||
&.selected { | ||
@apply bg-opacity-50; | ||
} | ||
} | ||
</style> | ||
|
||
<div class="grid px-4 py-2 rounded-2xl bg-white bg-opacity-50"> | ||
<div class="px-4 grid grid-flow-col gap-4 items-center font-bold"> | ||
{#each tabNames as tabName} | ||
<button | ||
class="tab w-full flex justify-center py-1 px-4 rounded-md" | ||
class:selected={tabName == currentTab} | ||
disabled={tabName == currentTab} | ||
on:click={() => currentTab = tabName} | ||
> | ||
{tabName} | ||
</button> | ||
{/each} | ||
</div> | ||
<div class="w-full h-1 bg-black bg-opacity-50 my-2 rounded-full" /> | ||
<div class="w-[32rem] h-64 py-2 font-semibold"> | ||
{#if currentTab == 'Information'} | ||
<div class="px-4 w-full h-full flex flex-col justify-between"> | ||
<div> | ||
<a class="text-2xl font-bold" href="https://vulae.github.io/infinite-minesweeper">Infinite Minesweeper</a> | ||
<br /> | ||
An infinite twist on Minesweeper that adds biomes that change the rules of the game. | ||
</div> | ||
<div class="pt-4"> | ||
<span class="float-right text-xs font-extrabold"> | ||
*Source code available on | ||
<a class="underline" href="https://github.com/Vulae/infinite-minesweeper">GitHub</a> | ||
</span> | ||
</div> | ||
</div> | ||
{:else if currentTab == 'Biomes'} | ||
<div class="w-full h-full inline"> | ||
<InfoModalBiomes /> | ||
</div> | ||
{:else if currentTab == 'Controls'} | ||
<div class="px-4"> | ||
<span> | ||
Left Click: Reveal tile | ||
<br /> | ||
Right Click: Flag tile | ||
<br /> | ||
Middle Click: Move view | ||
<br /> | ||
Scroll Wheel: Zoom view | ||
<br /> | ||
<br /> | ||
Arrow Keys: Move view | ||
<br /> | ||
Open Square Bracket '[': View zoom In | ||
<br /> | ||
Close Square Bracket ']': View zoom Out | ||
<br /> | ||
</span> | ||
</div> | ||
{/if} | ||
</div> | ||
</div> |
Oops, something went wrong.
8ba188d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice!