Snake Game

Challenge

This project offered a dual opportunity: to enhance my React.js, styled-components, GIT, and Netlify.io skills and delve into the realm of blockchain technology and NFTs.


Challenges centered on game logic, user interface design, and Ethereum blockchain integration. These hurdles advanced my technical proficiency and broadened my grasp of blockchain's possibilities.

Project Type

Front End Development

Tech stack

React.js, Styled Components

My Role

UI Designer and Developer

Stakeholder / Client

Personal Project

The Snake game isn't just a typical React.js project—it's my personal venture into merging classic gaming with blockchain technology.


Why Snake? It's about making blockchain fun and accessible. Through the game, conceptually you can create blockchain accounts with Metamask and earn Snake Tokens, an ERC-20 token that lets you customize the game.


Beyond just being a concept, this game boasts a fully operational game and blockchain interface. This project is a platform for entertainment and education, allowing me to sharpen my skills in React.js, styled components, GIT, and blockchain technology.

The Snake game isn't just a typical React.js and Styled Components project. It's my personal journey to blend the world of classic gaming with the exciting realm of blockchain technology. You might be wondering, "Why the Snake game?" Well, the primary goal here is to make blockchain technology accessible and fun for players like you.


In this game, you have the power to create your own blockchain accounts directly from the console, thanks to the magic of Metamask connectivity. As you enjoy playing and improving your scores, you'll earn Snake Tokens, a special ERC-20 token. These tokens aren't just points; they're your key to customizing the game with different colors and unique head icons. And the best part? The project isn't just a concept; it already offers a fully functional user interface and a prototype for integrating blockchain right on the front end.

2

Libraries

14

Components

1200+

Lines of Clean & Scalable Code

Process

As my first medium-scale independent coding project, my primary goal was to acquire proficiency in Front End Libraries and grasp blockchain concepts while exploring ways to incorporate these skills into a simple game. The development journey is well-documented in the Github repository, showcasing the project's evolution over numerous iterations.


The initial iteration involved local CSS and hard-coded text labels and values. However, as the project progressed, I transitioned to a CSS framework with Styled Components, ensuring a consistent visual style throughout the game. I also introduced a Constant file to centralize static values, promoting scalability and maintainability.


In parallel with coding the game logic, I implemented a continuous integration pipeline using GitHub and Netlify. This setup allowed me to efficiently deploy changes directly from my VS Code environment to the production website, streamlining the development workflow.

Solution

The game's UI features a blend of retro and modern aesthetics. Game logic, including snake movement, growth, bait generation, and game-over conditions, is coded in vanilla JavaScript and React.js. React Hooks, like UseContext and UseReducer, manage state and logic. A 'constants.js' file centralizes static content, CSS, and variables. Styled Components localize CSS. Built with Create-React-App, NPM manages modules.

The UI

The Game play screen and the game console are where the blockchain transactions are made.

Game Play
Game Console

Code Snippet - Movement Logic

Out of all the code written, I am most proud of the Reducer code. This file is responsible for the core game logic like Snake movement, eating the bait, and game-over conditions to name a few of many. While you can look at the Movement Logic here, It will be more interesting for me to take you through the complete Reducer File.

 case MOVE_SNAKE:
      const current_y = state.matrixPos.findIndex(
        (item) => item[0].top === state.snake.headPos.top
      );
      const current_x = state.matrixPos[current_y].findIndex(
        (item) => item.left === state.snake.headPos.left
      );
      const body = [
        state.matrixPos[current_y][current_x],
        ...state.snake.body.slice(0, -1),
      ];

      let new_x = current_x;
      let new_y = current_y;

      if (state.snake.direction === directions.up) {
        new_y++;
      }
      if (state.snake.direction === directions.down) {
        new_y--;
      }
      if (state.snake.direction === directions.left) {
        new_x--;
      }
      if (state.snake.direction === directions.right) {
        new_x++;
      }

      if (new_x < 0 || new_x > 39 || new_y < 0 || new_y > 15) {
        return {
          score: 0,
          speed: 1,
          matrixPos: state.matrixPos,
          play: false,
          mousePosition:
            state.matrixPos[mouseStartPosition.top][mouseStartPosition.left],
          snake: {
            headPos:
              state.matrixPos[snakeStartPosition.top][snakeStartPosition.left],
            body: [
              state.matrixPos[snakeStartPosition.top][
                snakeStartPosition.left - 1
              ],
              state.matrixPos[snakeStartPosition.top][
                snakeStartPosition.left - 2
              ],
            ],
            direction: directions.right,
          },
          validDirection: true,
          showModal: true,
        };
      }

      const selfBite = state.snake.body.some((item) => {
        return (
          item.top === state.matrixPos[new_y][new_x].top &&
          item.left === state.matrixPos[new_y][new_x].left
        );
      });

      if (selfBite) {
        return {
          score: 0,
          speed: 1,
          matrixPos: state.matrixPos,
          play: false,
          mousePosition:
            state.matrixPos[mouseStartPosition.top][mouseStartPosition.left],
          snake: {
            headPos:
              state.matrixPos[snakeStartPosition.top][snakeStartPosition.left],
            body: [
              state.matrixPos[snakeStartPosition.top][
                snakeStartPosition.left - 1
              ],
              state.matrixPos[snakeStartPosition.top][
                snakeStartPosition.left - 2
              ],
            ],
            direction: directions.right,
          },
          validDirection: true,
          showModal: true,
        };
      }

      return {
        ...state,
        snake: {
          ...state.snake,
          body,
          headPos: state.matrixPos[new_y][new_x],
        },
      };

Conclusion

Reflecting on this journey, I've acquired technical expertise in the product development pipeline, blockchain concepts, and React.js and embraced the value of an iterative, agile development approach. I initially developed the game, followed by blockchain integration, and later applied the pipeline to scale up.


Looking ahead, potential improvements encompass thorough documentation, robust exception handling for blockchain integrations, and UI and UX enhancements. Future steps involve refining the game's user interface, bolstering blockchain API integration, and addressing documentation and error handling.

Ready to Play the Game or Explore the Code?

Here are links

Next Project

Paani Foundation - Case Study

Transforming Paani Foundation's desktop website for better usability.

User Research

Usability Test

Prototype

Recommendations

Research

View

Paani Foundation - Case Study

Transforming Paani Foundation's desktop website for better usability.

User Research

Usability Test

Prototype

Recommendations

Research

View

Paani Foundation - Case Study

Transforming Paani Foundation's desktop website for better usability.

User Research

Usability Test

Prototype

Recommendations

Research

View

Hit me up for Work Opportunities or Collaborations.

Time to shatter that ice! Say hi and break the chill!

© Nishad Patne | 2024

Hit me up for Work Opportunities or Collaborations.

Time to shatter that ice! Say hi and break the chill!

© Nishad Patne | 2024