Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SkribblUp.io

A realtime browser-based drawing and guessing game, skribbl.io clone.

Technologies Used

This game was built using the following technologies:

  • React JS: A popular JavaScript library for building user interfaces.
  • SignalR : A library for building real-time web applications.
  • HTML and CSS: The languages used for creating the user interface and styling the game.

Demo Video

Demo Video

How To Play

  1. Navigate to the game in your web browser by visiting http://localhost:5000.
  2. Enter your username and choose a room then click "Join Room".
  3. Once there are enough players in the lobby, the game will start.
  4. If its your turn, you will be given three random secret words to choose from.
  5. Use the drawing tools to create an image that represents the secret word you've just choosen.
  6. When you're done drawing, the other players will have a limited amount of time to guess the word.
  7. If someone guesses the word correctly will earn points accroding to the order of guessing.
  8. The first player who reaches a 3000 points will take the 1st place. the 2nd and 3rd will also be announced.

How to Run

With Docker

  1. Clone the repository: git clone https://github.com/mohammed0xff/SkribblUp.io
  2. Navigate to the project directory: cd SkribblUp.io
  3. Run the Docker Compose command to build and start the containers: docker-compose up
  4. Open your web browser and go to http://localhost:5000

Without Docker

Backend end

  1. Clone the repository: git clone https://github.com/mohammed0xff/SkribblUp.io
  2. Navigate to the project directory: cd Backend/DrawAndGuess
  3. Build the project: dotnet build
  4. Run the project with launch settings: dotnet run
  • or just open .sln file and press f5 to build and run the project -

front end

  1. Navigate to the project directory: cd Frontend
  2. Install dependencies with: npm install
  3. Start the development server with: npm run dev or just vite
  4. Open your web browser and go to http://localhost:5000.

Workflow

Example : user started by sending a message ..

  1. In React app --> Chat Component
// user sends a message
sendMessage = async (message) => {
  try {
    await this.props.connection.invoke(InvokeMethods.SendMessage, message);
  } catch (e) {
    console.log(e);
  }
}
  1. Chathub recieves a call on SendMessage method providing a string parameter message
public class GameHub : Hub
{
    private readonly ICommandProcessor _commandProcessor;

    public void SendMessage(string message)
    {
        // creates a SendMessageCommand and pass it to command processor.
        _commandProcessor.AddCommand(
            new SendMessageCommand(Context.ConnectionId) { Message = message }
            );
    }

    // other hub methods here ..
}

By using the command pattern, the application is more maintainable and extensible, as each command encapsulates a specific action or behavior that can be easily added or modified. The command pattern also helps to decouple the logic of executing actions from the rest of our application.

  1. In CommandProcessor class
public class CommandProcessor : ICommandProcessor
{
  private readonly Game _game;
  private readonly ILogger<CommandProcessor> _logger;
  private readonly TaskQueue _taskQueue;

  public void AddCommand(ICommand command)
  {
      _taskQueue.EnqueueTask(
              () => ProcessCommand(command)
          );
  }

  private async Task ProcessCommand(ICommand command)
  {
      try
      {
         await command.ExecuteAsync(_game);
      }
      catch (Exception ex)
      {
          _logger.LogError($"Error in executing command {command.GetType().Name} : {ex.Message}");
      }
  }
}
  1. Command executes asynchronous in the task queue
public class SendMessageCommand : ICommand
{
    public string ConnectionId { get; init; }
    public string Message { get; init; }
    
    public async Task ExecuteAsync(Game game)
    {
        var user = game.GetUserByConnectionId(ConnectionId);
        
        // some exception handling here..
        //
        
        // send message only if it doesnt contain a right guess.
        if (! await game.CheckRightGuess(user, Message))
        {
            await game.Broadcaster.SendMessage(user, Message);
        }
    }
}
  1. Broadcaster Sends the message to room if user didn't make a right guess.
public async Task SendMessage(User user, string message)
{
    try
    {
        await SendToGroup(user.Room, ClientMethods.ReceiveMessage,
            new Message
            {
                Username = user.UserName,
                Content = message
            });
    }
    catch (Exception ex)
    {
        _logger.LogError($"Error sending message for user {user.UserName} in room {user.Room}: {ex.Message}");
    }
}
  1. As client code listens on ReceiveMessage
connection.on(ListeningMethods.ReceiveMessage, ({username, content}) => {
  this.setState(prevState => ({
    messages : [...prevState.messages, { username, content}] 
  }));
});
  1. All users in the room receive the message successfully.

Contributing

If you'd like to contribute, feel free to submit a pull request!

upcomming features

  • Backend :

    • sending errors to client.
    • announcing winners.
    • make some commands require certain permissions or challenges before they can be executed.
  • Frontend :

    • brush sizing.
    • eraser (actually, we just turn the drawing color white 😀).
    • fill tool
    • make it responsive

License

This game is licensed under the MIT license. See LICENSE.md for more information.

About

A realtime drawing game like skribbl.io made with React JS and asp.net core 7 signalR

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages