Skip to content

Commit

Permalink
Prepare for mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
matthijsgroen committed Sep 12, 2024
1 parent d0e8040 commit 66d1d39
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 92 deletions.
51 changes: 51 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true

jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: "yarn"
- name: Install dependencies
run: yarn
- name: Build
run: yarn build
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload dist folder
path: "./dist"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
12 changes: 7 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { LevelTrack } from "./modules/LevelTrack/index.tsx";
import PWABadge from "./PWABadge.tsx";
import { Level } from "./modules/Level/index.tsx";
import { generateNewSeed } from "./support/random.ts";
import { generateNewSeed, mulberry32 } from "./support/random.ts";
import {
getHardSettings,
getNormalSettings,
getSpecialSettings,
} from "./game/levelSettings.ts";
import { isHard, isSpecial } from "./modules/LevelTrack/levelType.ts";

const BASE_SEED = 12345678901234;

Expand All @@ -24,14 +25,15 @@ export const App: React.FC = () => {
setLevelSeed(generateNewSeed(BASE_SEED, levelNr));
}, [levelNr]);

const special = (levelNr + 1) % 10 === 6;
const hard = (levelNr + 1) % 10 === 8;
const special = isSpecial(levelNr);
const hard = isHard(levelNr);
const random = mulberry32(levelSeed);

const settings = hard
? getHardSettings(levelNr)
: special
? getSpecialSettings(levelNr)
: getNormalSettings(levelNr);
: getNormalSettings(random, levelNr);

return (
<>
Expand Down
30 changes: 30 additions & 0 deletions src/components/Block.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.shape {
text-shadow: 0px 0px 0px #888, 1px 1px 2px #000;
color: transparent;
opacity: 40%;
}

.texture {
background: url("./wood-texture.png");
mix-blend-mode: color-burn;
opacity: 60%;
}

.gradient {
background: linear-gradient(
rgba(0, 0, 0, 10%) 0%,
rgba(0, 0, 0, 0%) 20%,
rgba(0, 0, 0, 0%) 85%,
rgba(0, 0, 0, 50%) 100%
);
}

.gradientLocked {
transition: opacity 1s;
background: linear-gradient(
rgba(0, 0, 0, 50%) 0%,
rgba(0, 0, 0, 40%) 20%,
rgba(0, 0, 0, 40%) 85%,
rgba(0, 0, 0, 60%) 100%
);
}
33 changes: 26 additions & 7 deletions src/components/Block.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { shapeMapping } from "../game/blocks";
import { BlockColor } from "../game/types";
import styles from "./Block.module.css";

export type Props = {
moved: boolean;
revealed?: boolean;
color: BlockColor;
selected?: boolean | null;
locked?: boolean | null;
};

const colorMap: Record<BlockColor, string> = {
Expand All @@ -14,27 +17,43 @@ const colorMap: Record<BlockColor, string> = {
blue: "bg-blue-500",
purple: "bg-purple-500",
black: "bg-slate-800",
green: "bg-green-500",
green: "bg-green-600",
darkgreen: "bg-green-200",
aqua: "bg-blue-100",
brown: "bg-block-brown",
pink: "bg-pink-800",
pink: "bg-orange-200",
};

export const Block: React.FC<Props> = ({
revealed,
color,
moved,
selected = null,
locked = false,
}) => (
<div
className={`w-8 h-8 text-center pt-1 ${
className={`relative size-10 text-center animate-place ${
moved ? "" : "[animation-duration:0ms]"
} ${
revealed === false ? "bg-slate-500" : colorMap[color]
} rounded-md border ${
} rounded-md border border-block-brown/80
${
selected
? "border-white outline outline-white -translate-y-3 ease-in-out transition-transform animate-wobble"
: "border-black"
? "outline-2 outline-white outline -translate-y-6 ease-in-out transition-transform animate-wobble"
: ""
}`}
>
{revealed === false ? "?" : shapeMapping[color]}
<div className={`absolute z-10 size-10 pt-2 rounded-md`}>
<span className={`inline-block ${styles.shape}`}>
{revealed === false ? "?" : shapeMapping[color]}
</span>
</div>
<div className={`absolute size-10 rounded-md ${styles.texture}`}></div>
<div className={`absolute size-10 rounded-md ${styles.gradient}`}></div>
<div
className={`absolute size-10 -top-[2px] -left-[2px] ${
styles.gradientLocked
} ${locked ? "opacity-100" : "opacity-0"}`}
></div>
</div>
);
Binary file added src/components/wood-texture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/game/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ export const shapeMapping: Record<BlockColor, string> = {
yellow: "🟡",
aqua: "⚡️ ",
pink: "🐾",
purple: "✡️ ",
blue: "",
purple: "️⭐️",
blue: "🌙",
red: "❌",
white: "🔲",
green: "🔶",
Expand Down
3 changes: 3 additions & 0 deletions src/game/generateLevel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe(generatePlayableLevel, () => {
createPlacementColumn(4),
createPlacementColumn(4),
],
movesNeeded: 10,
});
});

Expand All @@ -101,6 +102,7 @@ describe(generatePlayableLevel, () => {
extraPlacementStacks: 2,
});
expect(level.colors).toHaveLength(7);
expect(level.movesNeeded).toEqual(39);
});

it("generates a complex level (buffers / force)", () => {
Expand All @@ -114,6 +116,7 @@ describe(generatePlayableLevel, () => {
bufferSizes: 4,
});
expect(level.colors).toHaveLength(4);
expect(level.movesNeeded).toEqual(259);
});

it("throws an error if it can't generate a playable level", () => {
Expand Down
22 changes: 14 additions & 8 deletions src/game/generateLevel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,49 @@ export type LevelSettings = {
export const generatePlayableLevel = (
random: () => number,
settings: LevelSettings
) => {
): LevelState => {
let attempt = 0;

while (attempt < 100) {
while (attempt < 10) {
attempt++;
const level = generateLevel(random, settings);
if (isStuck(level)) {
continue;
}
if (isBeatable(random, level)) {
return level;
const [beatable, moves] = isBeatable(random, level);
if (beatable) {
return { ...level, movesNeeded: moves };
}
}
throw new Error("Can't generate playable level");
};

const isBeatable = (random: () => number, level: LevelState): boolean => {
const isBeatable = (
random: () => number,
level: LevelState
): [beatable: boolean, moves: number] => {
let attempt = 0;

while (attempt < 50) {
while (attempt < 10) {
let playLevel = level;
let moves = 0;

while (!isStuck(playLevel)) {
const nextMove = getMove(random, playLevel);
if (!nextMove) {
break;
} else {
moves++;
playLevel = moveBlocks(playLevel, nextMove[0], nextMove[1]);
}
if (hasWon(playLevel)) {
return true;
return [true, moves];
}
}
attempt++;
}

return false;
return [false, 0];
};

const getMove = (
Expand Down
24 changes: 7 additions & 17 deletions src/game/levelSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,18 @@ const getSetting = (
min +
Math.min(Math.max(Math.floor((level - offset) / progression), 0), max - min);

export const getNormalSettings = (levelNr: number): LevelSettings => {
const amountColors = levelNr === 0 ? 2 : getSetting(levelNr, 3, 7, 4, 4);
const stackSize = getSetting(levelNr, 4, 8, 8, 10);
const extraPlacementLimits = levelNr > 100 && levelNr % 10 === 3 ? 1 : 0;

// amountColors={2}
// stackSize={4}
// extraPlacementStacks={1}

// amountColors={levelNr + 7}
// stackSize={16}
// buffers={3}
// bufferSizes={4}
// extraPlacementLimits={1}
// extraPlacementStacks={1}
// hideBlockTypes={true}
export const getNormalSettings = (
random: () => number,
levelNr: number
): LevelSettings => {
const amountColors = levelNr === 0 ? 2 : getSetting(levelNr, 3, 9, 0, 1); // 3, 9, 4, 4
const stackSize = 4;

return {
amountColors,
stackSize,
extraPlacementStacks: amountColors < 3 ? 1 : 2,
extraPlacementLimits,
hideBlockTypes: levelNr > 10 ? random() > 0.5 : false,
};
};

Expand Down
1 change: 1 addition & 0 deletions src/game/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { type BlockColor } from "./blocks";
export type LevelState = {
colors: BlockColor[];
columns: Column[];
movesNeeded?: number;
};

export type Block = {
Expand Down
5 changes: 5 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
background-image: url("./components/wood-texture.png");
background-color: brown;
}
Loading

0 comments on commit 66d1d39

Please sign in to comment.