Baseado nos jogos de simulação de vida, como The Sims, Tamagotchi e Pou, em UntitledGameDuck o jogador deve cuidar de um animal de estimação virtual
Visitar demostraçãoUm jogo desenvolvido com JavaScript, utilizando componentes React e estilizado com a component library Grommet (styled components), baseado nos jogos de simulação de vida, como The Sims, Tamagotchi e Pou, em que o jogador deve cuidar de um animal de estimação virtual (inicialmente um pato), mantendo suas necessidades em níveis positivos, para que o humor do bichinho mantenha-se bom e não termine em um trágico “game over”.
Implementado como parte de estudos independentes para aprimoramento dos conhecimentos de UI, Web Components e do framework React.
Visualmente elaborado com um design neuromórfico, em botões e containers, e plano para ícones, animações e emoticons.
As animações do personagem e o próprio foram idealizadas para serem simples e repetitivas, com formas geométricas básicas, permitindo o desenvolvimento utilizando transformações com CSS e Javascript, sem a necessidade de engines ou programas complexos para desenvolvimento de jogos. As ilustrações foram feitas utilizando o software Illustrator e transferidas para o AfterEffects, este possui um plugin chamado BodyMovin que permite a exportação da animação como um objeto JSON para ser renderizado na web ou em aplicações utilizando a biblioteca Lottie.
Utilizei React Redux para gerenciar os estados. Ao iniciar um novo jogo o objeto, a seguir, é definido como default para a store como estado inicial:
const state = {
// as mensagens que são mostradas como notificações durante o jogo
global_messages: [],
// a velocidade atual do jogo
current_speed: 1,
// as seis necessidades do personagem
needs: { ...needs },
// a fila de ações que devem ser executadas para preencher as necessidades
actions: [],
// vidas disponíveis para o personagem
lifes: 3,
// estado do personagem, o jogo executa enquanto 'ALIVE' e para quando 'DEAD'
status: 'ALIVE',
// humor do personagem contendo o valor, a legenda e os modificadores (que inicialmente estará vazio)
mood: {
value: 10,
label: 'unhappy',
mods: {
sad: {
value: -10,
timeout: 10000,
emoji: '😥',
label: 'sad',
description: 'Duck is sad'
},
...
}
}
}
Se o usuário optar por carregar um jogo salvo, o reducer recebe um estado anteriormente salvo no localStorage.
As atualizações do estado são feitas a cada segundo, disparadas por um componente chamado GameRunner. Este componente atualmente apenas executa uma ação e pode parecer dispensável, porém foi pensado para em atualizações futuras mostrar diferentes estilos para a interface.
const GameRunner = ({ updateGame, game_state }) => {
useEffect(() => {
const interval = setInterval(() => {
updateGame(game_state)
}, 1000);
return () => clearInterval(interval)
}, [game_state])
return <Text weight="bold">{game_state.current_speed}</Text>
}
As atualizações ficam por conta da action “updateGame”, que é uma função encarregada de disparar multiplos side effects no estado atual do jogo, como:
export const updateGame = state => {
return dispatch => {
if (state.lifes === 0) {
dispatch(killDuck())
} else {
const current_action = getCurrentAction(state, dispatch)
const updated_needs = updateNeeds(state, current_action)
const border_keys = getBorderNeedsKeys(updated_needs)
removeCurrentActionIfFullfied(current_action, border_keys, dispatch)
const mood_mods = getMoodMods(border_keys)
const updated_mood = updateMood(mood_mods, state.mood, dispatch)
if (updated_mood.value <= 0) {
dispatch(decrementLifes())
} else {
dispatch(setNeeds(updated_needs))
dispatch(setMood(updated_mood))
}
}
}
}
O código completo encontrasse no meu perfil do GitHub ou pode ser diretamente acessado por aqui.
O objetivo não era criar um jogo que pudesse ser publicado para várias pessoas se divertirem, mas sim praticar todas as tecnológias web citadas neste artigo. Portanto a continuação do desenvolvimento e correção de erros ficarão à cargo do meu tempo livre disponível.
Se quiser fazer um comentário ou saber mais detalhes, ficarei feliz de lhe responder no e-mail ou no meu twitter.