Skip to content

Commit

Permalink
Merge pull request #15 from JollyGrin/feat/refactor-state-for-2p
Browse files Browse the repository at this point in the history
Feat/refactor state for 2p
  • Loading branch information
JollyGrin authored Sep 12, 2024
2 parents a8fa71e + 2f4f0ce commit 4cd4408
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 136 deletions.
49 changes: 9 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,9 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Playtest Sorcery TCG in the browser

## Todo
- [ ] add health counter
- [ ] landing page
- [ ] add realms app deck loader
- [ ] add solo turn rotator (play against yourself)
- use top header for info
- [ ] add websocket
52 changes: 52 additions & 0 deletions daily.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");

// Get today's date in the required format
const today = new Date();
const formattedDate = today.toISOString().split("T")[0]; // YYYY-MM-DD format
const formattedTime = today.toTimeString().split(" ")[0].slice(0, 5); // HH:MM format

// Path to the daily note in the relative 'notes' folder
const notesDir = path.join(__dirname, "notes");
const notePath = path.join(notesDir, `${formattedDate}.md`);

// Check if the file exists, if not create it
if (!fs.existsSync(notePath)) {
fs.writeFileSync(notePath, "");
}

// Function to add an entry to the daily note
const addEntry = (entryText, isTodo) => {
// Read the file contents
const fileContent = fs.readFileSync(notePath, "utf-8");
const lastTimeStamp = (fileContent.match(/#### (\d{2}:\d{2})/g) || []).pop();

let newContent = "";

// If the last timestamp is not equal to the current time, add a new timestamp
if (!lastTimeStamp || lastTimeStamp !== `#### ${formattedTime}`) {
newContent += `\n#### ${formattedTime}\n`;
}

if (isTodo) {
newContent += `- [ ] ${entryText}\n`;
} else {
newContent += `- ${entryText}\n`;
}

fs.appendFileSync(notePath, newContent);
};

// Main script
// const command = process.argv[2];
const command = "add";
const entryText = process.argv.slice(3).join(" ");

if (command === "add" || command === "todo") {
const isTodo = command === "todo";
addEntry(entryText, isTodo);
} else {
// Open the note in the default editor
execSync(`vi "${notePath}"`, { stdio: "inherit" });
}
1 change: 1 addition & 0 deletions notes/2024-09-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

12 changes: 12 additions & 0 deletions notes/2024-09-12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#### 02:37
- im making progress in setting up the multiplayer but now im running into an issue of every player is updating the same thing

#### 02:38
- actually i might be getting somewhere

#### 02:49
- okay i got it working but now i have to solve auras

#### 03:18
- i got it working. the tricky thing with auras was i had to adjust the top left values because they would always look the same no matter the order
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"note": "node daily.js"
},
"dependencies": {
"@dnd-kit/core": "^6.1.0",
Expand Down
30 changes: 19 additions & 11 deletions src/components/organisms/GameBoard/Auras/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,39 @@ import { Modal } from "@/components/atoms/Modal";
import { FullCardAtlas } from "@/components/atoms/card-view/atlas";
import { CardImage as FullCard } from "@/components/atoms/card-view/card";
import { CARD_CDN, GRIDS } from "../constants";
import { useRouter } from "next/router";

export const Auras = (props: GameStateActions) => {
return (
<Box position="absolute" w="100%" h="100%">
{Array.from({ length: 12 }).map((_, index) => (
<Aura
key={"aura" + index}
card={props.gridItems?.[GRIDS.AURA_1 + index]?.[0]}
gridIndex={GRIDS.AURA_1 + index}
index={0}
/>
))}
{Array.from({ length: 12 })
.map((_, index) => index)
.map((index) => (
<Aura
key={"aura" + index}
card={props.gridItems?.[GRIDS.AURA_1 + index]?.[0]}
gridIndex={GRIDS.AURA_1 + index}
index={0}
/>
))}
</Box>
);
};

const Aura = (props: { card: GameCard; gridIndex: number; index: number }) => {
const auraCard = props.card;
const { query } = useRouter();
const name = query?.name ?? "p1";
const isReversed = name === "p2";

const auraCard = props.card;
const auraIndex = props.gridIndex - GRIDS.AURA_1; // normalize to zero
const topIndex = Math.floor(auraIndex / 4) + 1; // increments every 4
const top = `${topIndex * 25}%`; // in percent
// const top = `${topIndex * 25}%`; // in percent
const leftIndex = 1 + (auraIndex % 4); // every 4, resets
const left = `${leftIndex * 20}%`; // in percent
// const left = `${leftIndex * 20}%`; // in percent

const top = isReversed ? `${(4 - topIndex) * 25}%` : `${topIndex * 25}%`; // Reverse top
const left = isReversed ? `${(5 - leftIndex) * 20}%` : `${leftIndex * 20}%`; // Reverse left
return (
<Box
style={{
Expand Down
10 changes: 10 additions & 0 deletions src/components/organisms/GameBoard/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LAYOUT_HEIGHTS } from "./constants";
import { GameFooter } from "./Footer";
import { GameStateActions } from ".";
import { Auras } from "./Auras";
import Link from "next/link";

const { nav, body, footer } = LAYOUT_HEIGHTS;

Expand All @@ -18,11 +19,20 @@ export const GameLayout = (
background: "rgba(0,200,0,0.2)",
padding: "0.5rem",
height: nav,
display: "flex",
gap: "2rem",
}}
>
<p style={{ width: "fit-content" }}>
Playtest cards on a grid. Click to tap. Right click to view big.
</p>
<Link href={{ query: { name: "p1" } }}>
<p>p1</p>
</Link>

<Link href={{ query: { name: "p2" } }}>
<p>p2</p>
</Link>
</div>
<Box position="relative" h="100%" w="100%" maxW="1200px" m="0 auto">
<Auras {...props} />
Expand Down
8 changes: 7 additions & 1 deletion src/components/organisms/GameBoard/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export const LAYOUT_HEIGHTS = { nav, footer, body };
* GRID ORDERING
*
* Contains the grid, auras, hand, deck, atlas deck, grave
* grave is last element in enum
* */

export enum GRIDS {
GRID_1,
GRID_2,
Expand Down Expand Up @@ -57,3 +57,9 @@ export enum GRIDS {
ATLAS_DECK,
GRAVE,
}

/**
* Length of hand, deck, deck-atlas, and grave (4)
* used to splice playerstate from global state
* */
export const GRIDS_PERSONAL_LENGTH = GRIDS.GRAVE - GRIDS.AURA_12;
121 changes: 52 additions & 69 deletions src/components/organisms/GameBoard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,71 @@ import { CardAtlas } from "@/components/atoms/mock-cards/atlas";
import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable";
import { GameLayout } from "./Layout";
import { DroppableGridItem } from "@/components/molecules/DropGridItem";
import {
closestCenter,
closestCorners,
CollisionDetection,
DndContext,
DragOverlay,
} from "@dnd-kit/core";
import { DndContext, DragOverlay } from "@dnd-kit/core";
import { useHandleDrag } from "./useHandleDrag";
import { CardImage } from "@/components/atoms/mock-cards/card";
import { CardImage as FullCard } from "@/components/atoms/card-view/card";
import { SortableItem } from "@/components/molecules/SortItem";
import { Box } from "styled-system/jsx";
import { Modal } from "@/components/atoms/Modal";

import { Dispatch, SetStateAction, useState } from "react";
import { useState } from "react";
import { FullCardAtlas } from "@/components/atoms/card-view/atlas";
import { GameCard, GameState } from "@/types/card";
import { GRIDS } from "./constants";
import { useRouter } from "next/router";

export type GameStateActions = {
gridItems: GameState;
setGridItems: Dispatch<SetStateAction<GameState>>;
setGridItems: (state: GameState) => void;
};
export const GameBoard = ({ gridItems, setGridItems }: GameStateActions) => {
const { sensors, handleDragEnd, handleDragStart, activeId, activeCard } =
useHandleDrag({
gridItems,
setGridItems,
});
const { query } = useRouter();

const collision: CollisionDetection = (props) => {
// Access the current translated Y position of the dragged item
const currentY = props?.active?.rect?.current?.translated?.top;
const { activeCard, activeId, ...dragProps } = useHandleDrag({
gridItems,
setGridItems,
});

// Get the height of the viewport
const viewportHeight = window.innerHeight;

// Check if the current Y position is within the bottom 170px of the page
const isInFooter = currentY && currentY > viewportHeight - 170;

// Check if the current Y position is within the bottom 170px of the page
// If the item is in the bottom 170px, use closestCenter for the footer
if (isInFooter) {
return closestCenter(props);
}

return closestCorners(props);
};
const name = query?.name ?? "p1";
const isReversed = name === "p2";

return (
<DndContext
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
collisionDetection={collision}
sensors={sensors}
>
<DndContext {...dragProps}>
<GameLayout gridItems={gridItems} setGridItems={setGridItems}>
{gridItems?.slice(0, 20)?.map((cards, gridIndex) => (
<DroppableGridItem
key={"grid-" + gridIndex}
id={gridIndex.toString()}
gridIndex={gridIndex}
style={{ overflowY: "auto", overflowX: "clip" }}
>
<SortableContext
id={`grid-${gridIndex}`}
items={cards.map((card) => card.id)}
strategy={rectSortingStrategy}
{(isReversed
? gridItems.slice(0, 20).reverse()
: gridItems.slice(0, 20)
)?.map((cards, _gridIndex) => {
// Adjust the gridIndex if array was reversed
const gridIndex = isReversed
? GRIDS.GRID_20 - _gridIndex
: _gridIndex;

return (
<DroppableGridItem
key={"grid-" + gridIndex}
id={gridIndex.toString()}
gridIndex={gridIndex}
style={{ overflowY: "auto", overflowX: "clip" }}
>
{cards.map((card, cardIndex) => (
<SortItemWrapper
key={card.id}
amountOfCards={cards?.length}
{...{ gridItems, setGridItems }}
{...{ card, gridIndex, cardIndex }}
/>
))}
</SortableContext>
</DroppableGridItem>
))}
<SortableContext
id={`grid-${gridIndex}`}
items={cards.map((card) => card.id)}
strategy={rectSortingStrategy}
>
{cards.map((card, cardIndex) => (
<SortItemWrapper
key={card.id}
amountOfCards={cards?.length}
{...{ gridItems, setGridItems }}
{...{ card, gridIndex, cardIndex }}
/>
))}
</SortableContext>
</DroppableGridItem>
);
})}
</GameLayout>
<DragOverlay>
{activeId ? (
Expand Down Expand Up @@ -119,16 +105,13 @@ const SortItemWrapper = ({

const isTapped = card.isTapped;
function toggleTap() {
props.setGridItems(() => {
const newGrid = [...props.gridItems];
const card = newGrid[gridIndex][cardIndex];
newGrid[gridIndex][cardIndex] = {
...card,
isTapped: !card.isTapped,
} as GameCard;

return newGrid;
});
const newGrid = [...props.gridItems];
const card = newGrid[gridIndex][cardIndex];
newGrid[gridIndex][cardIndex] = {
...card,
isTapped: !card.isTapped,
} as GameCard;
props.setGridItems(newGrid);
}

return (
Expand Down
Loading

0 comments on commit 4cd4408

Please sign in to comment.