Skip to content

Commit

Permalink
feat(collab): added collaborative canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvkjain committed Sep 4, 2024
1 parent 2b62eba commit 9f6cef9
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 15 deletions.
5 changes: 4 additions & 1 deletion backend/src/config/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const { Server } = require('socket.io');
const { verifyToken } = require('../utils');
const games = require('../models/game.model.js');
const { createRoom, joinRoom, disconnected, generateWord, setCurrentWord, checkGuess } = require('../services/game.services.js');
const { getData, storeData } = require('../config/redis.js');

function socketConnection(server) {

Expand Down Expand Up @@ -156,6 +155,10 @@ function socketConnection(server) {
callback(res);
})

socket.on('draw-line', async(prevPoint, currentPoint, secretcode) => {
socket.to(secretcode).emit('draw-line', {prevPoint, currentPoint})
})

// socket.onAny((event, ...args) => {
// console.log(event, args);
// });
Expand Down
33 changes: 29 additions & 4 deletions frontend/src/context/GameContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext, useState, ReactNode } from "react";
import { createContext, useContext, useState, useRef, ReactNode, MutableRefObject } from "react";

export type player = {
username: string;
Expand All @@ -12,6 +12,11 @@ export type gameResponse = {
error?: string;
}

type Point = {
x:number;
y:number;
}

type words = [string] | undefined

export type GameContextType = {
Expand All @@ -21,6 +26,10 @@ export type GameContextType = {
setOpenDialog: (open: boolean) => void;
words: [string] | undefined;
setWords: (words: words) => void;
canvasRef: MutableRefObject<HTMLCanvasElement | null>;
prevPoint: MutableRefObject<Point | null>;
mouseDown: boolean;
setMouseDown: (newValue: boolean) => void;
}
type ContextProps = {
children: ReactNode;
Expand All @@ -33,10 +42,26 @@ function GameContextProvider({ children }: ContextProps) {
const [gameDetails, setGameDetails] = useState<gameResponse | undefined>(undefined);
const [openDialog, setOpenDialog] = useState<boolean>(false);
const [words, setWords] = useState<words>(undefined);
const canvasRef = useRef<HTMLCanvasElement>(null);
const prevPoint = useRef<null | Point>(null);
const [mouseDown, setMouseDown] = useState<boolean>(false);

return <GameContext.Provider value={{ gameDetails, setGameDetails, openDialog, setOpenDialog, words, setWords }}>
{children}
</GameContext.Provider>
return (
<GameContext.Provider value={{
gameDetails,
setGameDetails,
openDialog,
setOpenDialog,
words,
setWords,
canvasRef,
prevPoint,
mouseDown,
setMouseDown,
}}>
{children}
</GameContext.Provider>
)
}

function useGameContext() {
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/hooks/useDraw.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from "react";
import { useEffect } from "react";

export type Draw = {
ctx: CanvasRenderingContext2D;
Expand All @@ -16,10 +16,11 @@ export type Point = {
y:number;
}

import { useGameContext, GameContextType } from "../context/GameContext.tsx";

const useDraw = (drawLine:({currentPoint, prevPoint}:DrawPoints)=>void) =>{
const canvasRef = useRef<HTMLCanvasElement>(null);
const prevPoint = useRef<null | Point>(null);
const [mouseDown, setMouseDown] = useState<boolean>(false);

const { canvasRef, prevPoint, mouseDown, setMouseDown, } = useGameContext() as GameContextType;

const onMouseDown =()=>{setMouseDown(true)}
const mouseUphandler =()=>{
Expand Down
36 changes: 34 additions & 2 deletions frontend/src/hooks/useSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { io, Socket } from 'socket.io-client';

import { useAuthContext, AuthContextType } from "../context/AuthContext.tsx";
import { gameResponse, useGameContext, GameContextType } from "../context/GameContext.tsx";
import { useDraw, DrawPoints } from "./useDraw.ts";
import { useDraw, DrawPoints, Draw } from "./useDraw.ts";

export type roomCode = {
error?: string;
Expand All @@ -30,7 +30,7 @@ function useSocket() {

const { authUser } = useAuthContext() as AuthContextType;
const { setGameDetails, setOpenDialog, setWords } = useGameContext() as GameContextType;
const { clearCanvas } = useDraw(drawLine);
const { clearCanvas, canvasRef } = useDraw(drawLine);

const createSocketConnection = () => {
if (socket) return; // Prevent re-initialization
Expand Down Expand Up @@ -110,6 +110,38 @@ function useSocket() {
}
});

socket.on('draw-line', ({prevPoint, currentPoint}:DrawPoints)=>{
const canvas = canvasRef.current;
if(!canvas){
return;
}

const ctx = canvas.getContext('2d');
if(!ctx){
return;
}

function onDraw({ctx, currentPoint, prevPoint}:Draw){
const { x:currX, y:currY } = currentPoint;
const lineColor = '#ffff';
const lineWidth = 5;

const startPoint = prevPoint ?? currentPoint;
ctx.beginPath();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = lineColor;
ctx.moveTo(startPoint.x , startPoint.y);
ctx.lineTo(currX, currY);
ctx.stroke();

ctx.fillStyle = lineColor;
ctx.beginPath();
ctx.arc(startPoint.x, startPoint.y, 2, 0, 2*Math.PI);
ctx.fill();
}
onDraw({ctx, currentPoint, prevPoint});
})

socket.on("select-word", gameData => {
setWords(gameData);
setOpenDialog(true);
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/pages/Account.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { memo } from 'react';

import { Button } from "@/components/ui/button"
import {
Card,
Expand Down Expand Up @@ -106,4 +108,4 @@ function Account() {
)
}

export default Account;
export default memo(Account);
4 changes: 2 additions & 2 deletions frontend/src/pages/Game.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, memo } from 'react';
import { useNavigate } from 'react-router-dom';

import { Input } from "@/components/ui/input"
Expand Down Expand Up @@ -161,4 +161,4 @@ function Game() {
)
}

export default Game
export default memo(Game)
3 changes: 2 additions & 1 deletion frontend/src/pages/GameMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { memo } from 'react';
import { useNavigate } from 'react-router-dom';

import { Button } from "@/components/ui/button"
Expand Down Expand Up @@ -90,4 +91,4 @@ function GameMenu() {
)
}

export default GameMenu
export default memo(GameMenu)

0 comments on commit 9f6cef9

Please sign in to comment.