diff --git a/app/back-end/game/consumers.py b/app/back-end/game/consumers.py index b6f42b4f..a5eef9e2 100644 --- a/app/back-end/game/consumers.py +++ b/app/back-end/game/consumers.py @@ -230,6 +230,22 @@ async def start_game(self): # delete_room(self.room_name) return await self.broadcast_message({"action": "start_game"}) + message = { + "action": "score", + "user1score": room.getScores()["user1"], + "user2score": room.getScores()["user2"], + } + await self.broadcast_message(message) + ball_position, ball_velocity = room.get_updated_ball() + message = { + "action": "update", + "ball_position_x": ball_position["x"], + "ball_position_z": ball_position["z"], + "ball_velocity_x": ball_velocity["velocity_x"], + "ball_velocity_z": ball_velocity["velocity_z"], + } + await self.broadcast_message(message) + await asyncio.sleep(5) room.ball_update() room.ball_intersect() room.paddle_update() diff --git a/app/front-end/src/app/dashboard/page.tsx b/app/front-end/src/app/dashboard/page.tsx index 5cf90f18..ae3333bd 100644 --- a/app/front-end/src/app/dashboard/page.tsx +++ b/app/front-end/src/app/dashboard/page.tsx @@ -16,12 +16,12 @@ import { LineController } from 'chart.js/auto'; import { useRouter } from 'next/navigation' import { Dropdown } from 'react-bootstrap'; import ExportCSV from '@/components/export'; -import { CategoryScale, - LinearScale, - Title, - Legend, +import { CategoryScale, + LinearScale, + Title, + Legend, Tooltip, - PointElement, + PointElement, LineElement } from 'chart.js'; interface TotalMinutes { @@ -71,7 +71,7 @@ export default function Dashboard() { const gameData: GameData[] = []; const gameCsv: GameData[] = []; useEffect(() => { - const fetchData = async () => + const fetchData = async () => { const access = Cookies.get('access'); @@ -105,8 +105,8 @@ export default function Dashboard() { const period = 'year'; const response = await fetch('http://localhost:8000/api/game-stats-report', { method: 'POST', - headers: - { + headers: + { Authorization: `Bearer ${access}` , 'Content-Type': 'application/json' }, @@ -175,17 +175,17 @@ export default function Dashboard() { const chartLabels = dashboardData?.total_minutes.months || []; const chartData = dashboardData?.total_minutes.minutes_months || []; - + Chart.register( - CategoryScale, - LinearScale, - Title, - Legend, - Tooltip, - LineController, - PointElement, + CategoryScale, + LinearScale, + Title, + Legend, + Tooltip, + LineController, + PointElement, LineElement); - + Chart.defaults.font.family = 'Itim'; Chart.defaults.font.size = 14; const options: ChartOptions<'line'> = { @@ -200,7 +200,7 @@ export default function Dashboard() { }, }, }; - + const labels: string[] = chartLabels; const data: ChartData<'line'> = { labels, @@ -216,100 +216,169 @@ export default function Dashboard() { }; return ( -
- {/* {csvData && } */} -
-
-
-
-
-
- upcoming -
-
-
-

THE ULTIMATE PING-PONG GAME.

-
-
-
-
-
Welcome to our online ping pong paradise! Dive into - the fast-paced world of table tennis with our website, - where players of all levels can connect, compete, - and improve their skills. From casual matches to intense - tournaments, we've got everything you need to serve up some - excitement! -
-
-
- -
-
-
-
-
-
- anime charachter -
-
+
+ {/* {csvData && } */} +
+
+
+
+
+
+ + upcoming + +
+
+
+

+ THE ULTIMATE PING-PONG GAME. +

+
+
+
+
+ Welcome to our online ping pong paradise! Dive into the + fast-paced world of table tennis with our website, where + players of all levels can connect, compete, and improve + their skills. From casual matches to intense + tournaments, we've got everything you need to serve up + some excitement! +
+
+
+ +
+
+
+
+
+
+ anime charachter
-
-
-
-
-
-
-

GAME HISTORY

-
-
- - - ALL - +
+
+
+
+
+
+
+
+
+

+ GAME HISTORY +

+
+
+ + + ALL + - - This Day - This Month - This Year - - -
-
-
- -
-
-
-
-
-
-

MY GAME STATS

-
-
- - - ALL - + + + This Day + + + This Month + + + This Year + + + +
+
+
+ +
+
+
+
+
+
+

+ MY GAME STATS +

+
+
+ + + ALL + - - This Month - 3 Months - 1 Year - - -
-
-
-
-
 
- -
-
-
+ + + This Month + + + 3 Months + + + 1 Year + + +
+
+
+
+
 
+ +
+
+
+
); -} \ No newline at end of file +} diff --git a/app/front-end/src/app/game/(choose-opponent)/chooseOpponent.tsx b/app/front-end/src/app/game/(choose-opponent)/chooseOpponent.tsx index ca9ccc88..f8e81e41 100644 --- a/app/front-end/src/app/game/(choose-opponent)/chooseOpponent.tsx +++ b/app/front-end/src/app/game/(choose-opponent)/chooseOpponent.tsx @@ -41,12 +41,12 @@ function ChooseOpponent({ setPageId }: Props) {
- - + +
diff --git a/app/front-end/src/app/game/(choose-opponent)/styles.module.css b/app/front-end/src/app/game/(choose-opponent)/styles.module.css index f543096e..f66c6751 100644 --- a/app/front-end/src/app/game/(choose-opponent)/styles.module.css +++ b/app/front-end/src/app/game/(choose-opponent)/styles.module.css @@ -1,40 +1,34 @@ h1.cards { - font-size: clamp(1rem, 0.8182rem + 0.5818vw, 3rem); - color : var(--clr-red); - border-top: var(--clr--white); - background-color: var(--clr-ldark); - border-bottom-left-radius: 25px; - border-bottom-right-radius: 25px; + font-size: clamp(1rem, 0.8182rem + 0.5818vw, 3rem); + color: var(--clr-red); + border-top: var(--clr--white); + background-color: var(--clr-ldark); + border-bottom-left-radius: 25px; + border-bottom-right-radius: 25px; } .wrapper { - gap : 20px 5%; - overflow: auto; + gap: 20px 5%; + overflow: auto; } div.option { - min-width: 100px; - cursor: pointer; + width: 250px; + height: 500px; + cursor: pointer; + transition: all 0.5s ease; + filter: grayscale(80%); + border-radius: 25px; } div.option:hover { - scale: 1.09; + filter: grayscale(0%); + scale: 1.1; } img.cards { - background-color: var(--clr-ldark); - border-top-right-radius: 25px; - border-top-left-radius: 25px; - height: clamp(100px, 45vw - 2vw, 600px); -} - -@media (max-width : 776px) { - h1.cards { - border-radius: 10px; - } - - img.cards { - min-width: 100px; - height: 250px; - } + background-color: var(--clr-ldark); + border-top-right-radius: 25px; + border-top-left-radius: 25px; + height: 400px; } diff --git a/app/front-end/src/components/PlayerCard/PlayerCard.tsx b/app/front-end/src/components/PlayerCard/PlayerCard.tsx index 126e13b5..060e52c5 100644 --- a/app/front-end/src/components/PlayerCard/PlayerCard.tsx +++ b/app/front-end/src/components/PlayerCard/PlayerCard.tsx @@ -48,7 +48,7 @@ const PlayerCard: React.FC = ({ > {name}
-

{name}

+

{name || "player"}

diff --git a/app/front-end/src/components/PongGame/PongGame.tsx b/app/front-end/src/components/PongGame/PongGame.tsx index 7c94eb08..373fa1d1 100644 --- a/app/front-end/src/components/PongGame/PongGame.tsx +++ b/app/front-end/src/components/PongGame/PongGame.tsx @@ -9,7 +9,7 @@ import Ball from "./Ball"; import Paddle from "./Paddle"; import "./PongGame.css"; import BoardItem from "../BoardItem/BoardItem"; - +import gsap from "gsap"; interface ConnectionInfo { index: number; roomName: string; @@ -39,59 +39,47 @@ const PongGame: React.FC = ({ players, }: Props) => { const containerRef = useRef(null); - const [dimensions, setDimensions] = useState({ - width: 0, - height: window.innerHeight, - }); const [user1score, setUser1Score] = useState(0); const [user2score, setUser2Score] = useState(0); - const yoruImage = "/yoru.jpeg"; - const omenImage = "/omen.jpeg"; - - useEffect(() => { - function updateDimensions() { - if (containerRef.current) { - setDimensions({ - width: containerRef.current.clientWidth, - height: window.innerHeight, - }); - } - } - - window.addEventListener("resize", updateDimensions); - updateDimensions(); - - return () => { - window.removeEventListener("resize", updateDimensions); - }; - }, []); useEffect(() => { + const { current: container } = containerRef; + if (!container) return; + let width = container.clientWidth; + let height = window.innerHeight; const newScene = new THREE.Scene(); newScene.background = new THREE.Color(0x000000); const newCamera = new THREE.PerspectiveCamera( 75, - dimensions.width / window.innerHeight, + width / height, 0.1, 1000 ); - if (dimensions.width < 600) newCamera.fov = 100; - else if (dimensions.width >= 600 && dimensions.width < 1024) - newCamera.fov = 90; + if (width < 500) newCamera.fov = 120; + else if (width >= 500 && width < 1000) newCamera.fov = 100; + else if (width >= 1000 && width < 1200) newCamera.fov = 90; else newCamera.fov = 75; - // newCamera.position.set(0, 5, 0); - newCamera.position.set(6, 8, 0); - newCamera.lookAt(new THREE.Vector3(9, 9, 0)); + newCamera.updateProjectionMatrix(); + // newCamera.position.set(5, 0, 5); + newCamera.position.set(5, 0, 5); + const targetPosition = new THREE.Vector3(6, 8, 0); + gsap.to(newCamera.position, { + x: targetPosition.x, + y: targetPosition.y, + z: targetPosition.z, + duration: 3, + onUpdate: () => { + newCamera.lookAt(new THREE.Vector3(0, 0, 0)); + }, + }); const newRenderer = new THREE.WebGLRenderer(); - newRenderer.setSize(dimensions.width, window.innerHeight); - const { current: container } = containerRef; - if (container) container.appendChild(newRenderer.domElement); - + newRenderer.setSize(width, height); + container.appendChild(newRenderer.domElement); const controls = new OrbitControls(newCamera, newRenderer.domElement); controls.enableZoom = true; controls.enablePan = true; controls.minDistance = 10; - controls.maxDistance = 160; + controls.maxDistance = 120; controls.update(); const surface = new Surface(10, 5, 1, 1, 0x161625); @@ -134,12 +122,8 @@ const PongGame: React.FC = ({ directionalLight.position.set(0, 10, 0); newScene.add(directionalLight); - const light = new THREE.PointLight(0xffffff, 0.5); - light.position.set( - ball.mesh.position.x, - ball.mesh.position.y + 0.1, - ball.mesh.position.z - ); + const light = new THREE.PointLight(0xffffff, 1); + light.position.copy(ball.mesh.position).y += 0.1; newScene.add(light); const handleKeyDown = (event: KeyboardEvent) => { @@ -174,13 +158,15 @@ const PongGame: React.FC = ({ }; const handleResize = () => { - if (dimensions.width < 600) newCamera.fov = 100; - else if (dimensions.width >= 600 && dimensions.width < 1024) - newCamera.fov = 90; + let width = container.clientWidth; + let height = window.innerHeight; + if (width < 500) newCamera.fov = 120; + else if (width >= 500 && width < 1000) newCamera.fov = 100; + else if (width >= 1000 && width < 1200) newCamera.fov = 90; else newCamera.fov = 75; - newCamera.aspect = dimensions.width / dimensions.height; + newCamera.aspect = width / height; newCamera.updateProjectionMatrix(); - newRenderer.setSize(dimensions.width, dimensions.height); + newRenderer.setSize(width, height); }; const sendMessage = (data: Record) => { @@ -193,52 +179,36 @@ const PongGame: React.FC = ({ const handleMessage = (event: MessageEvent) => { const data = JSON.parse(event.data); if (data.message.action === "update") { - if (connectionInfo.index === 1) - ball.update( - data.message.ball_position_x, - data.message.ball_position_z, - data.message.ball_velocity_x, - data.message.ball_velocity_z - ); - else - ball.update( - data.message.ball_position_x * -1, - data.message.ball_position_z * -1, - data.message.ball_velocity_x * -1, - data.message.ball_velocity_z * -1 - ); - light.position.copy(ball.mesh.position); + const factor = connectionInfo.index === 1 ? 1 : -1; + ball.update( + data.message.ball_position_x * factor, + data.message.ball_position_z * factor, + data.message.ball_velocity_x * factor, + data.message.ball_velocity_z * factor + ); + light.position.copy(ball.mesh.position).y += 0.1; } if (data.message.action === "reset") { - if (connectionInfo.index === 1) - ball.update( - 0, - data.message.ball_position_z, - data.message.ball_velocity_x, - data.message.ball_velocity_z - ); - else - ball.update( - 0, - data.message.ball_position_z * -1, - data.message.ball_velocity_x * -1, - data.message.ball_velocity_z * -1 - ); - light.position.copy(ball.mesh.position); + const factor = connectionInfo.index === 1 ? 1 : -1; + ball.update( + 0, + data.message.ball_position_z * factor, + data.message.ball_velocity_x * factor, + data.message.ball_velocity_z * factor + ); + light.position.copy(ball.mesh.position).y += 0.1; paddle1.reset(); paddle2.reset(); } if (data.message.action === "paddle_update") { - if (connectionInfo.index === 1) { - if (data.message.paddle === 1) - paddle1.update(data.message.paddle_position_z); - if (data.message.paddle === 2) - paddle2.update(data.message.paddle_position_z); - } else { - if (data.message.paddle === 1) - paddle2.update(data.message.paddle_position_z * -1); - if (data.message.paddle === 2) - paddle1.update(data.message.paddle_position_z * -1); + const factor = connectionInfo.index === 1 ? 1 : -1; + const updatePaddle1 = connectionInfo.index === 1 ? paddle1 : paddle2; + const updatePaddle2 = connectionInfo.index === 1 ? paddle2 : paddle1; + if (data.message.paddle === 1) { + updatePaddle1.update(data.message.paddle_position_z * factor); + } + if (data.message.paddle === 2) { + updatePaddle2.update(data.message.paddle_position_z * factor); } } if (data.message.action === "score") { @@ -259,6 +229,7 @@ const PongGame: React.FC = ({ animate(); return () => { + console.log("PongGame unmounted"); webSocket.removeEventListener("message", handleMessage); document.removeEventListener("keydown", handleKeyDown); document.removeEventListener("keyup", handleKeyUp); @@ -270,19 +241,19 @@ const PongGame: React.FC = ({ } } }; - }, [dimensions, connectionInfo, webSocket, user1score, user2score]); + }, []); return (