diff --git a/SerpentRace_Frontend/src/App.jsx b/SerpentRace_Frontend/src/App.jsx
index 8f9be082..f6ee0b0c 100644
--- a/SerpentRace_Frontend/src/App.jsx
+++ b/SerpentRace_Frontend/src/App.jsx
@@ -10,7 +10,8 @@ import Landingpage from "./pages/Landing/Landingpage"
import Home from "./pages/Landing/Home"
import DeckManagerPage from "./pages/Decks/DeckManagerPage"
import About from "./pages/About/About"
-import ScrollToTop from "./components/ScrollToTop";
+import ScrollToTop from "./components/ScrollToTop"
+import GameScreen from "./pages/Game/GameScreen"
function App() {
const [isMobile, setIsMobile] = useState(false)
@@ -40,22 +41,20 @@ function App() {
return (
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- {/* Add more routes as needed */}
-
-
-
-
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ {/* Add more routes as needed */}
+
)
}
diff --git a/SerpentRace_Frontend/src/pages/Game/GameScreen.jsx b/SerpentRace_Frontend/src/pages/Game/GameScreen.jsx
new file mode 100644
index 00000000..364f1af1
--- /dev/null
+++ b/SerpentRace_Frontend/src/pages/Game/GameScreen.jsx
@@ -0,0 +1,235 @@
+import React, { useState } from "react"
+import { getVerticalOffset } from "../../utils/randomUtils"
+import Dice from "../../utils/dice/Dice"
+
+const GameScreen = () => {
+ const boardRows = 5
+ const boardCols = 20
+ const totalCells = boardRows * boardCols
+ const cellSize = 40
+ const cellMargin = 2.5
+ const rowSpacing = 70 // Extra spacing between rows
+ const topOffset = rowSpacing * 0.5 // Increase topOffset for more spacing
+ const bottomOffset = rowSpacing * 0.5 // Increase bottomOffset for more spacing
+ const boardWidthPx = boardCols * (cellSize + cellMargin * 2)
+ const boardHeightPx =
+ boardRows * (cellSize + cellMargin * 2 + rowSpacing) + topOffset + bottomOffset - rowSpacing
+
+ // Generate a snake-like path with vertical spacing and vertical offsets
+ const generateWindingPath = () => {
+ const path = []
+ let currentNum = 1
+
+ for (let row = 0; row < boardRows && currentNum <= totalCells; row++) {
+ // Calculate the y position with extra row spacing
+ const baseYPosition = topOffset + row * (cellSize + cellMargin * 2 + rowSpacing)
+
+ // If row number is even, go right; if odd, go left
+ if (row % 2 === 0) {
+ // Left to right
+ for (let col = 0; col < boardCols && currentNum <= totalCells; col++) {
+ path.push({
+ number: currentNum++,
+ x: col * (cellSize + cellMargin * 2),
+ y: baseYPosition + getVerticalOffset(currentNum - 1),
+ type: getFieldType(currentNum - 1),
+ })
+ }
+ } else {
+ // Right to left
+ for (let col = boardCols - 1; col >= 0 && currentNum <= totalCells; col--) {
+ path.push({
+ number: currentNum++,
+ x: col * (cellSize + cellMargin * 2),
+ y: baseYPosition + getVerticalOffset(currentNum - 1),
+ type: getFieldType(currentNum - 1),
+ })
+ }
+ }
+ }
+
+ return path
+ }
+
+ const getFieldType = (count) => {
+ if (count % 17 === 0) return "clover"
+ if (count % 13 === 0) return "bad"
+ if ((count + 5) % 13 === 0) return "good"
+ return "regular"
+ }
+
+ const [path, setPath] = useState(generateWindingPath())
+ const [players, setPlayers] = useState([
+ { id: 1, name: "Béla", position: 34, score: 25, color: "bg-blue-600", emoji: "🐍" },
+ { id: 2, name: "Juci", position: 50, score: 30, color: "bg-green-600", emoji: "🐢" },
+ { id: 3, name: "Kati", position: 70, score: 15, color: "bg-purple-600", emoji: "🐇" },
+ { id: 3, name: "Fürtös", position: 68, score: 14, color: "bg-yellow-600", emoji: "😂" },
+ ])
+
+ // Sort players by position in descending order
+ const sortedPlayers = [...players].sort((a, b) => b.position - a.position)
+
+ // Handle dice roll
+ const handleDiceRoll = (value) => {
+ console.log("Rolled:", value)
+ // You can add logic here to move the current player based on the dice value
+ }
+
+ console.log("Generated path length:", path.length)
+
+ const getFieldStyle = (type) => {
+ switch (type) {
+ case "clover":
+ return "bg-teal-700 border-teal-500 shadow-teal-800"
+ case "bad":
+ return "bg-red-800 border-red-600 shadow-red-900"
+ case "good":
+ return "bg-blue-800 border-blue-600 shadow-blue-900"
+ default:
+ return "bg-gray-800 border-gray-600 shadow-gray-900"
+ }
+ }
+
+ const getPlayerPosition = (playerPosition) => {
+ const field = path.find((p) => p.number === playerPosition)
+ return field ? { top: `${field.y}px`, left: `${field.x}px` } : { top: 0, left: 0 }
+ }
+
+ // Function to get medal style based on rank
+ const getMedalStyle = (rank) => {
+ switch (rank) {
+ case 1:
+ return "bg-yellow-400 text-yellow-900 border-yellow-500 shadow-yellow-600"
+ case 2:
+ return "bg-gray-400 text-gray-900 border-gray-500 shadow-gray-600"
+ case 3:
+ return "bg-orange-500 text-orange-900 border-orange-600 shadow-orange-700"
+ default:
+ return "bg-gray-700 text-gray-300 border-gray-600 shadow-gray-800"
+ }
+ }
+
+ return (
+
+
+
+ {/* Game Board */}
+
+ {/* Háttér */}
+
+ {[...Array(35)].map((_, i) => (
+ // Sajat pulse effect! => node_modules/tailwindcss/index.css:
+ // --animate-pulse8: pulse 6s cubic-bezier(0.4, 0.2, 0.6, 1) infinite;
+
+
+ ))}
+
+
+ {/* Mezők */}
+ {path.map((field) => (
+
+ {field.number}
+
+ ))}
+
+ {/* Player tokens */}
+ {players.map((player) => (
+
+ {player.emoji}
+
+ ))}
+
+
+ {/* Game information */}
+ {/*
+
+ Sima
+ Lóhere
+ Rossz
+ Jó
+
+
*/}
+
+
+ {/* Right sidebar */}
+
+
+
Játékosok
+ {sortedPlayers.map((player, index) => (
+
+
+ {player.emoji}
+
+
+
+ {player.name}
+
+ {index + 1 === 1
+ ? "🥇 1st"
+ : index + 1 === 2
+ ? "🥈 2nd"
+ : index + 1 === 3
+ ? "🥉 3rd"
+ : `${index + 1}th`}
+
+
+
+ Pozíció: {player.position} • Pontszám: {player.score}
+
+
+
+ ))}
+
+
+ {/* Dice Container */}
+
+
Dobókocka
+
Kattints a kockára dobáshoz!
+
+
+
+
+
+
+ )
+}
+
+export default GameScreen
diff --git a/SerpentRace_Frontend/src/utils/MrandomUtils.js b/SerpentRace_Frontend/src/utils/MrandomUtils.js
new file mode 100644
index 00000000..994d8c5d
--- /dev/null
+++ b/SerpentRace_Frontend/src/utils/MrandomUtils.js
@@ -0,0 +1,24 @@
+// Scaling factor for vertical offsets
+const offsetScalingFactor = 0.4;
+
+// Predefined vertical offsets represented as a 5x20 grid of zeros
+export const verticalOffsets = [
+ 0,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+];
+
+/**
+ * Gets a vertical offset value from the predefined array
+ * @param {number} index - Index to retrieve from the offsets array
+ * @returns {number} Offset value
+ */
+
+export const getVerticalOffset = (index) => {
+ const normalizedIndex = index % verticalOffsets.length;
+ const offset = verticalOffsets[normalizedIndex >= 0 ? normalizedIndex : 0];
+ return offset * offsetScalingFactor; // Apply scaling factor
+};
\ No newline at end of file
diff --git a/SerpentRace_Frontend/src/utils/dice/Dice.jsx b/SerpentRace_Frontend/src/utils/dice/Dice.jsx
new file mode 100644
index 00000000..756a69cf
--- /dev/null
+++ b/SerpentRace_Frontend/src/utils/dice/Dice.jsx
@@ -0,0 +1,139 @@
+import React, { useState, useEffect, useRef } from 'react';
+
+const Dice = ({ onRoll }) => {
+ const [diceValue, setDiceValue] = useState(1);
+ const [isRolling, setIsRolling] = useState(false);
+ const animationRef = useRef(null);
+ const rollTimeoutRef = useRef(null);
+
+ const diceFaces = [
+ [],
+ [, ],
+ [, , ],
+ [, ,
+ , ],
+ [, ,
+ ,
+ , ],
+ [, ,
+ , ,
+ , ]
+ ];
+
+ useEffect(() => {
+ return () => {
+ if (animationRef.current) cancelAnimationFrame(animationRef.current);
+ if (rollTimeoutRef.current) clearTimeout(rollTimeoutRef.current);
+ };
+ }, []);
+
+ const rollDice = () => {
+ if (isRolling) return;
+
+ setIsRolling(true);
+
+ let duration = 0;
+ const rollInterval = 80; // ms between dice face changes
+ const maxDuration = 1500; // total animation time
+
+ const rollAnimation = () => {
+ const randomValue = Math.floor(Math.random() * 6) + 1;
+ setDiceValue(randomValue);
+
+ duration += rollInterval;
+
+ if (duration < maxDuration) {
+ // Speed effect: slow down towards the end
+ const nextInterval = rollInterval * (1 + (duration / maxDuration) * 2);
+ rollTimeoutRef.current = setTimeout(() => {
+ animationRef.current = requestAnimationFrame(rollAnimation);
+ }, nextInterval);
+ } else {
+ // Final roll
+ const finalValue = Math.floor(Math.random() * 6) + 1;
+ setDiceValue(finalValue);
+ setIsRolling(false);
+
+ if (onRoll) onRoll(finalValue);
+ }
+ };
+
+ animationRef.current = requestAnimationFrame(rollAnimation);
+ };
+
+ return (
+
+
+ {diceFaces[diceValue - 1]}
+
+
+
+ );
+};
+
+export default Dice;
diff --git a/SerpentRace_Frontend/src/utils/randomUtils.js b/SerpentRace_Frontend/src/utils/randomUtils.js
new file mode 100644
index 00000000..c9502414
--- /dev/null
+++ b/SerpentRace_Frontend/src/utils/randomUtils.js
@@ -0,0 +1,20 @@
+// Predefined vertical offsets represented as a 5x20 grid of zeros
+export const verticalOffsets = [
+ 0,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+ -35, -10, -5, 10, 15, 12, 5, -5, -12, -15, -12, -5, 5, 12, 15, 12, 5, -5, 10, 35,
+];
+
+/**
+ * Gets a vertical offset value from the predefined array
+ * @param {number} index - Index to retrieve from the offsets array
+ * @returns {number} Offset value
+ */
+
+export const getVerticalOffset = (index) => {
+ const normalizedIndex = index % verticalOffsets.length;
+ return verticalOffsets[normalizedIndex >= 0 ? normalizedIndex : 0];
+};
\ No newline at end of file