Memory Bits
Data 30/06/2024
Atualizado
Data 30/06/2024
Atualizado
Video apresentação do projeto: https://www.youtube.com/watch?v=63Eg0b0iCdk Repositório: https://github.com/Merieli/memory-bits
Este projeto de estudo é de uma aplicação web FullStack do tipo SSR (Server-Side Rendering) com design criado por mim no Figma. A aplicação foi desenvolvida utilizando Nuxt 3 com Typescript, Vue Router, Pinia, Tailwind CSS, componentes Radix Vue, Zod, Prisma e banco de dados MySQL.
A proposta do projeto é criar um jogo da memória com banco de dados e API em estilo pixel art, onde cada jogador efetua seu login na aplicação.
O login no app é simplificado e elimina a necessidade de se cadastrar. Ao digitar um nome de usuário único e escolher o nível, a aplicação valida se o usuário já existe no banco de dados. Se existir, obtém os dados do usuário para iniciar; se não, cria um novo usuário com base no username fornecido.
Embora esse tipo de login não seja adequado para uma aplicação do mundo real, foi implementado dessa forma apenas para facilitar, focando no mais importante que era aprender sobre API e banco de dados. Em um cenário real, seria necessário criar uma área de cadastro e exigir o uso de senha para garantir a segurança.
Todo o esquema de pontuação do jogo é baseado no nível escolhido. Conforme a dificuldade aumenta, o tempo máximo permitido para o jogo diminui. Quando o tempo limite para o nível é atingido, o jogo é finalizado com a derrota do jogador. As tentativas erradas a cada seleção de pares também são contabilizadas e, ao atingirem o limite para o nível, resultam na derrota do jogador.
Optei por criar um endpoint para cada operação que desejava realizar no banco de dados, sendo assim foi criada a API abaixo: Cards:
GET
/cards
- para obter todas as cartas. Esse endpoint também permite os query params group_id, group_name e level_id para facilitar a busca de cartas pertencentes a grupos ou níveis específicos.
GET
/cards/:id
- para obter uma determinada carta pelo Id.
POST
/cards
- para salvar uma nova carta no banco de dados.
DELETE
/cards/:id
- para excluir uma carta do banco de dados.
Group of cards:
GET
/group_of_cards
- para obter todos os grupos de cartas.
GET
/group_of_cards/:name
- para obter os grupos de cartas pelo nome.
Levels:
GET
/levels
- para obter todos os níveis do jogo.
Matchs:
GET
/matchs
- para obter todas as partidas registradas. Também possui o query param user_id que permite a busca de todas as partidas de um determinado usuário.
GET
/matchs/:id
- para obter uma partida específica por Id.
POST
/matchs
- para salvar uma nova partida.
DELETE
/matchs/:id
- para excluir uma determinada partida por Id.
PUT
/matchs/:id
- para atualizar uma determinada partida por Id.
Users:
GET
/users
- para obter todos os usuários. Possui o query param name que permite a busca de um usuário pelo nome.
GET
/users/:id
- para obter um usuário específico por Id.
POST
/users
- para salvar um novo usuário.
O primeiro passo foi definir os requisitos do projeto, criando um roadmap detalhado de todas as etapas necessárias para a sua conclusão. A ideia inicial era criar um jogo da memória que permitisse aos jogadores selecionar o nível de dificuldade desejado e efetuar o login com seu usuário. Na tela do jogo, deveria ser possível visualizar detalhes como a pontuação, o nível, a quantidade de tentativas erradas e um contador de duração.
Na segunda etapa, desenvolvi um diagrama de caso de uso do jogo para facilitar a compreensão das funcionalidades e interações necessárias. Em seguida, passei para a definição do design no Figma, onde todas as telas foram cuidadosamente planejadas e desenhadas.
Como um dos objetivos do projeto era aprender a criar um banco de dados, optei por criar uma modelagem conceitual com um diagrama MER (Modelo Entidade-Relacionamento) e um diagrama DER (Diagrama Entidade-Relacionamento) para a modelagem lógica. E todo o script do banco de dados foi criado usando o MySQL Shell, desde os comandos para criar as tabelas até os de inserção de dados.
A ideia conceitual do projeto era usar o estilo pixel art e fazer referência a jogos conhecidos, como Mario e Tibia. A partir disso, escolhi uma fonte no estilo pixel art, a VT323 do Google Fonts, e selecionei imagens open-source em pixel art que representassem os ícones que queria usar no projeto, de forma a utilizar poucos textos e representar os elementos com ícones.
O nome do projeto, Memory Bits, foi inspirado pela escolha do pixel art que usa a coloração de quadrados que representam pontos de pixel, onde cada pixel é composto por "bits", uma unidade para armazenar informações digitais. E o "memory" vem de jogo da memória.
Foram criadas a página de login e a do jogo, enquanto que as telas de derrota e vitória foram pensadas como uma "cobertura" sobre a página principal, facilitando todo o processo de desenvolvimento.
O fundo escolhido foi uma paisagem em pixel art com céu e grama, de forma simples para não poluir o plano. E as cartas foram escolhidas de acordo com a complexidade das imagens para popular os níveis do jogo. As cartas com desenhos do Mario foram selecionadas para o nível Easy, enquanto as cartas do Tibia foram usadas nos níveis Medium e Hard, por possuírem mais elementos detalhados e alguns semelhantes que aumentam a dificuldade na escolha dos pares.
Neste projeto, aprendi a usar o Nuxt, banco de dados MySQL, a biblioteca de componentes Radix Vue, o Zod e o Prisma para desenvolver uma aplicação full-stack.
Com o Nuxt, pude aprender a criar uma aplicação SSR (Server-Side Rendering), que oferece um carregamento mais eficiente, proporcionando uma experiência prática com esse tipo de aplicação e conhecendo seus benefícios.
Aprendi a modelar, criar e manipular o banco de dados MySQL, que foi escolhido devido à sua popularidade e amplo uso no mercado, aplicando também algumas otimizações de tipos.
Com o ORM (Object-Relational Mapping) Prisma, tive a possibilidade de construir queries de forma simplificada para os endpoints da aplicação, facilitando a identificação de tipos e acelerando todo o processo de desenvolvimento.
O Zod permitiu validar os dados do banco de dados no formato pensado para a API, utilizando uma classe abstrata DTO (Data Transfer Object) que também faz a transformação dos dados. Por se tratar de um projeto full-stack, pude usar o mesmo esquema de validação no frontend e no backend, garantindo a aplicação das mesmas regras de validação em ambos os lados, evitando duplicação de código e mantendo a consistência dos dados.
O Radix Vue foi usado com a finalidade de experimentar componentes que proporcionassem acessibilidade. Nesse projeto, por ser simples, seu uso se limitou a selects e inputs.