Skip to content

Commit

Permalink
Functional pause button (fix #48)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcreedcmu committed Nov 12, 2023
1 parent 58ebfb0 commit 7698ce5
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 16 deletions.
4 changes: 4 additions & 0 deletions src/core/clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ export type PanicData = {
currentTime: number, // ms since epoch
};

export type PauseData = {
pauseTime: number, // ms since epoch
}

export const PANIC_INTERVAL_MS = 90000;

export function getPanicFraction(panic: PanicData) {
Expand Down
7 changes: 5 additions & 2 deletions src/core/reduce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Action, Effect, GameAction } from './action';
import { getPanicFraction } from './clock';
import { Overlay, getOverlayLayer, mkOverlay, mkOverlayFrom, overlayPoints, setOverlay } from './layer';
import { GameState, Location, SceneState, SelectionState, TileEntity, mkGameSceneState } from './state';
import { addWorldTiles, checkValid, drawOfState, filterExpiredAnimations, isCollision, isOccupied, isTilePinned, tryKillTileOfState } from './state-helpers';
import { addWorldTiles, checkValid, drawOfState, filterExpiredAnimations, isCollision, isOccupied, isTilePinned, tryKillTileOfState, unpauseState } from './state-helpers';
import { getTileId, get_hand_tiles, get_main_tiles, get_tiles, putTileInHand, putTileInWorld, removeAllTiles, setTileLoc } from "./tile-helpers";
import { Tool, currentTool, toolOfIndex } from './tools';

Expand Down Expand Up @@ -279,10 +279,13 @@ function reduceMouseDownInToolbar(state: GameState, wp: WidgetPoint & { t: 'tool
}

function reducePauseButton(state: GameState, wp: WidgetPoint): GameState {
return vacuous_down(state, wp);
return produce(vacuous_down(state, wp), s => { s.paused = { pauseTime: Date.now() }; });
}

function reduceMouseDown(state: GameState, wp: WidgetPoint, button: number, mods: Set<string>): GameState {
if (state.paused) {
return unpauseState(vacuous_down(state, wp), state.paused);
}
switch (wp.t) {
case 'world': return reduceMouseDownInWorld(state, wp, button, mods);
case 'hand': return reduceMouseDownInHand(state, wp, button, mods);
Expand Down
14 changes: 14 additions & 0 deletions src/core/state-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Point } from "../util/types";
import { vadd, vequal, vint } from "../util/vutil";
import { getAssets } from "./assets";
import { Bonus } from "./bonus";
import { PanicData, PauseData } from "./clock";
import { getLetterSample } from "./distribution";
import { checkConnected, checkGridWords, mkGridOfMainTiles } from "./grid";
import { Layer, Overlay, getOverlayLayer, overlayAny, overlayPoints, setOverlay } from "./layer";
Expand Down Expand Up @@ -165,3 +166,16 @@ export function isTilePinned(state: GameState, tileId: string, loc: Location & {
export function filterExpiredAnimations(now_ms: number, anims: Animation[]): Animation[] {
return anims.filter(anim => now_ms <= anim.start_ms + anim.duration_ms);
}

export function unpauseState(state: GameState, pause: PauseData): GameState {
if (state.panic) {
const newPanic: PanicData = {
currentTime: Date.now(),
lastClear: state.panic.lastClear + Date.now() - pause.pauseTime,
};
return produce(state, s => { s.panic = newPanic; s.paused = undefined; });
}
else {
return produce(state, s => { s.paused = undefined; });
}
}
4 changes: 3 additions & 1 deletion src/core/state.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SE2 } from '../util/se2';
import { Point } from '../util/types';
import { Bonus, bonusGenerator } from './bonus';
import { PanicData } from './clock';
import { PanicData, PauseData } from './clock';
import { Energies, initialEnergies } from './distribution';
import { Grid, LocatedWord, mkGridOf } from './grid';
import { Layer, Overlay, mkLayer, mkOverlay } from './layer';
Expand Down Expand Up @@ -89,6 +89,7 @@ export type GameState = {
selected?: SelectionState,
score: number,
panic: PanicData | undefined,
paused: PauseData | undefined,
};

export function mkSceneState(): SceneState {
Expand Down Expand Up @@ -121,5 +122,6 @@ export function mkGameState(seed?: number): GameState {
bonusOverlay: mkOverlay<Bonus>(),
score: 0,
panic: undefined,
paused: undefined,
};
}
1 change: 1 addition & 0 deletions src/ui/instructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ function exampleState(): GameState {
},
score: 7,
panic: { currentTime: Date.now(), lastClear: Date.now() - PANIC_INTERVAL_MS / 3 },
paused: undefined,
};

const tiles: Tile[] = [
Expand Down
22 changes: 18 additions & 4 deletions src/ui/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { LocatedWord, getGrid } from "../core/grid";
import { getOverlay, getOverlayLayer } from "../core/layer";
import { Animation, GameState, TileEntity } from "../core/state";
import { getTileId, get_hand_tiles, get_main_tiles, isSelectedForDrag } from "../core/tile-helpers";
import { debugOnce, logOnce } from "../util/debug";
import { fillRect, fillText, strokeRect } from "../util/dutil";
import { SE2, apply, compose, inverse, translate } from '../util/se2';
import { apply_to_rect } from "../util/se2-extra";
import { Point, Rect } from "../util/types";
import { boundRect } from "../util/util";
import { boundRect, midpointOfRect } from "../util/util";
import { vadd, vm, vscale, vsub, vtrans } from "../util/vutil";
import { CanvasInfo } from "./use-canvas";
import { canvas_from_drag_tile, pan_canvas_from_world_of_state } from "./view-helpers";
import { canvas_bds_in_canvas, canvas_from_hand, canvas_from_toolbar, hand_bds_in_canvas, toolbar_bds_in_canvas, world_bds_in_canvas } from "./widget-helpers";
import { canvas_bds_in_canvas, canvas_from_hand, canvas_from_toolbar, hand_bds_in_canvas, pause_button_bds_in_canvas, toolbar_bds_in_canvas, world_bds_in_canvas } from "./widget-helpers";

export function paintWithScale(ci: CanvasInfo, state: GameState) {
const { d } = ci;
Expand Down Expand Up @@ -47,8 +48,22 @@ function drawAnimation(d: CanvasRenderingContext2D, pan_canvas_from_world: SE2,

}

export function drawPausedScreen(ci: CanvasInfo, state: GameState) {
const { d } = ci;

fillRect(d, canvas_bds_in_canvas, 'white');

d.textAlign = 'center';
d.textBaseline = 'middle';
fillText(d, "paused", midpointOfRect(canvas_bds_in_canvas), 'black', '48px sans-serif');
}

export function rawPaint(ci: CanvasInfo, state: GameState) {

if (state.paused) {
drawPausedScreen(ci, state);
return;
}

const worldClip = new Path2D();
worldClip.rect(world_bds_in_canvas.p.x, world_bds_in_canvas.p.y,
Expand Down Expand Up @@ -175,10 +190,9 @@ export function rawPaint(ci: CanvasInfo, state: GameState) {
);
fillRect(d, rect_in_canvas, 'rgba(255, 255, 0, 0.5)');

const p_in_canvas = { x: S / 2, y: canvas_bds_in_canvas.sz.y - S / 2 };
d.textAlign = 'center';
d.textBaseline = 'middle';
fillText(d, "⏸", p_in_canvas, 'black', '48px sans-serif');
fillText(d, "⏸", midpointOfRect(pause_button_bds_in_canvas), 'black', '48px sans-serif');
}

function drawHand() {
Expand Down
16 changes: 8 additions & 8 deletions src/ui/widget-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const toolbar_bds_in_canvas: Rect = {
};

export const pause_button_bds_in_canvas: Rect = {
p: { x: 0, y: canvas_bds_in_canvas.sz.y },
p: { x: 0, y: canvas_bds_in_canvas.sz.y - TOOLBAR_WIDTH },
sz: { x: TOOLBAR_WIDTH, y: TOOLBAR_WIDTH }
};

Expand Down Expand Up @@ -55,7 +55,13 @@ export type WidgetPoint =
;

export function getWidgetPoint(state: GameState, p_in_canvas: Point): WidgetPoint {
if (pointInRect(p_in_canvas, toolbar_bds_in_canvas)) {
if (pointInRect(p_in_canvas, pause_button_bds_in_canvas)) {
return {
t: 'pauseButton',
p_in_canvas,
};
}
else if (pointInRect(p_in_canvas, toolbar_bds_in_canvas)) {
const toolbar_from_canvas = inverse(canvas_from_toolbar());
const p_in_local = apply(toolbar_from_canvas, p_in_canvas);
return {
Expand All @@ -66,12 +72,6 @@ export function getWidgetPoint(state: GameState, p_in_canvas: Point): WidgetPoin
toolIndex: Math.floor(p_in_local.y / toolbar_bds_in_canvas.sz.x),
}
}
else if (pointInRect(p_in_canvas, pause_button_bds_in_canvas)) {
return {
t: 'pauseButton',
p_in_canvas,
};
}
else return getDragWidgetPoint(state, p_in_canvas);
}

Expand Down
6 changes: 5 additions & 1 deletion src/util/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Point, Rect } from "./types";
import { vsub } from "./vutil";
import { vm2, vsub } from "./vutil";

export function mapval<T, U>(m: { [k: string]: T }, f: (x: T, k?: string) => U): { [k: string]: U } {
return Object.fromEntries(Object.entries(m).map(([k, v]) => [k, f(v, k)]));
Expand Down Expand Up @@ -88,3 +88,7 @@ export function point_hash(p: Point): number {
z();
return z();
}

export function midpointOfRect(rect: Rect): Point {
return vm2(rect.p, rect.sz, (p, s) => p + s / 2);
}

0 comments on commit 7698ce5

Please sign in to comment.