DEV Community

joaovmvini
joaovmvini

Posted on

INTRODUÇÃO AO LEMONADE JS

Antes de começarmos o tutorial

Vamos construir um pequeno jogo durante este tutorial. Este tutorial engloba várias técnicas do Lemonade, uma biblioteca javascript que tem como objetivo auxiliar na integração entre o javascript e o html. O lemonade oferece suporte a two-way binding e ajuda a criar interfaces incríveis mais rapidamente.

O que estamos construindo?

Neste tutorial, mostraremos como criar um jogo interativo de jogo da forca utilizando o Lemonade. Você pode ver o que vamos construir aqui: Hangman Game.

Recomendamos que você confira o jogo da forca antes de prosseguir com este tutorial para melhor entendimento do que será desenvolvido.

Pré-requisitos

Vamos presumir que você já tem um pouco de familiaridade com HTML e Javascript. Também vamos presumir que você já esteja familiarizado com alguns conceitos de programação. Tais como: Funções, objetos e arrays.

Caso você precise revisar o Javascript, recomendamos que leia este guia.

Configurações necessárias para o tutorial

Há duas maneiras de concluir este tutorial: você pode escrever o código em seu navegador ou configurar um ambiente de desenvolvimento local em seu computador.

Opção de configuração 1: Desenvolvendo código no Navegador

Esta é a maneira mais rápida para você começar!

Primeiro, abra este Código inicial em um novo guia. A nova aba deve exibir um template inicial para o jogo da forca e o código Lemonade. Nós iremos editar o código Lemonade neste tutorial.

Opção de configuração 2: Desenvolvendo em ambiente local

Esta opção requer um pouco mais de trabalho, mas possibilita que você complete o tutorial em um editor de código de sua preferência. Aqui estão os passos a serem seguidos:

  1. Certifique-se de ter uma versão recente do Node.js instalada.
  2. Vá até um diretório de sua preferência para a criação do exemplo
  3. Neste diretório, digite o seguinte comando no seu terminal:
npm i lemonadejs
Enter fullscreen mode Exit fullscreen mode

Ao executar o comando acima, você obterá uma pasta chamada node_modules que contém outras duas pastas: dist e src.

A pasta dist contém os arquivos de código-fonte do Lemonade para distribuição, e a pasta src contém o arquivo de código-fonte origem do Lemonade. Você pode escolher qualquer um destes arquivos para utilizar em seu projeto Lemonade.

  1. Crie um arquivo HTML no diretório do seu projeto com um nome de sua preferência, nós recomendamos hangman.html

Nós utilizaremos o seguinte código HTML inicial para iniciar nosso projeto:

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" 
         href="https://jsuites.net/v3/jsuites.layout.css" 
         type="text/css" />
        <title>Hangman Game LemonadeJS Example</title>
        <style>
            .word {
                   display: flex;
                   justify-content: space-evenly;
                   padding: 20px 0px;
            }

            .word span {
                        width: 25px;
                        border-bottom: 2px solid black;
                        display: inline-block;
            }
        </style>
    </head>
    <body>
        <div id="root"></div>  
    </body>
    <script type="text/javascript" src="./node_modules/lemonadejs/dist/lemonade.js"></script>
    </html>
Enter fullscreen mode Exit fullscreen mode

Perceba que ao final do código fonte temos uma linkagem para o arquivo do código-fonte do Lemonade, essa linkagem é necessária para que possamos utilizar as funcionalidades do LemonadeJS.

Tudo pronto! Agora podemos começar a desenvolver nosso jogo utilizando o Lemonade. Mas antes, precisamos de uma referência para um arquivo javascript onde desenvolvemos nosso código.

  1. Crie um novo arquivo javascript no diretório do seu projeto.
  2. Crie uma referência para o arquivo javascript criado anteriormente logo após a linkagem do Lemonade.
<script type="text/javascript" src="./node_modules/lemonadejs/dist/lemonade.js"></script>
<script type="text/javascript" src="./hangman.js"></script>
Enter fullscreen mode Exit fullscreen mode

Agora nós estamos prontos para iniciar o desenvolvimento do jogo-da-forca utilizando o Lemonade.

Criação do Template

No Lemonade nós podemos utilizar templates para renderizar elementos HTML em um elemento específico da nossa página. Vamos iniciar com o seguinte código no arquivo javascript que criamos:

var Hangman = (function() {
     // Nosso código será escrito aqui
});
Enter fullscreen mode Exit fullscreen mode

Repare que no nosso trecho de código HTML, temos o seguinte elemento:

<div id='root'></div>
Enter fullscreen mode Exit fullscreen mode

O elemento com o id “root” será o elemento que o Lemonade utilizará para renderizar nosso template. Mas antes disso, precisamos definir nosso template.

Para isso, criaremos uma variável que armazenará o template a ser renderizado.

var Hangman = (function() {

        var template = ``;
});
Enter fullscreen mode Exit fullscreen mode

Antes de montarmos nosso template, vale a pena conhecer a estrutura dele. A template será representada pela seguinte template string:

var Hangman = (function() {

        var template = `
        <div class='p20' style='width: 460px;'>
            <div style='border-left:2px solid black; border- 
            top:2px solid black; height: 
            160px;width:100px;padding-top:20px;'>
                <div style='position:absolute; margin-left:40px;'>
                    ${ /* SVG COMES HERE */ }
                </div>
            </div>
            <div @ready="self.renderLetters(this)" 
                 @ref="self.lettersElement" class="word" 
                 style='text-align: center'></div>
            <div style="display: flex; justify-content: space- 
                 between; align-items: center; padding: 10px;
                 min-width: 490px;">
                <div>
                    <label for="user-input">Input:</label>
                    <input type="text" name="user-input" 
                    placeholder="Enter a letter" 
                    onkeyup="self.check(this)"/> 
                </div>
                <input type="button" 
                onclick="self.resetGame(this)" value="Restart 
                Game" class="jbutton dark" /> <span 
                >Clue: </span>
            </div>
    </div>`;

Enter fullscreen mode Exit fullscreen mode

No ponto três nós mencionamos que iremos incluir um svg no espaço ${ SVG COMES HERE }, o svg tem o seguinte formato:

<svg class="stickman" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns1="http://sozi.baierouge.fr" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 168.38 357.72" width='60'>
                        <g transform="translate(-165.46 -71.804)">
                            <g  transform="translate(15.143 -322.57)">
                                <path id="stickman-1" d="m275 450.36c0 22.644-18.356 41-41 41s-41-18.356-41-41 18.356-41 41-41 41 18.356 41 41z" style=" visibility: hidden; stroke:#000000;stroke-width:10;fill:none" />
                                <path id="stickman-2" d="m234 511.91v138.91z" style=" visibility: hidden; stroke:#000000;stroke-width:8.4187;" />
                                <path id="stickman-5" d="m244 667.36 47 72z" style=" visibility: hidden; stroke:#000000;stroke-width:10;" />
                                <path id="stickman-6" d="m222.5 666.36-47 72z" style=" visibility: hidden; stroke:#000000;stroke-linecap:round;stroke-width:10;" />
                                <path id="stickman-3" d="m211.5 520.36-47 72z" style=" visibility: hidden; stroke:#000000;stroke-width:10;" />
                                <path id="stickman-4" d="m257.5 514.36 47 72z" style=" visibility: hidden; stroke:#000000;stroke-width:10;" />
                            </g>
                        </g>
                    </svg>
Enter fullscreen mode Exit fullscreen mode

SVG renderizado:

Alt Text

Se você observar bem o código do svg, perceberá que ele possui algumas tags “path” onde cada uma possue um id diferente, cada path desse corresponde à um membro do stickman acima que utilizaremos no nosso jogo, esse detalhe é muito importante!

Uma vez que temos nosso template pronto, podemos iniciar a implementação do código utilizando o Lemonade.

Antes de começar a desenvolver: Como o Lemonade funciona

Nós criamos um template com um propósito, e o propósito é renderizá-lo em um ponto específico da página HTML e definirmos estado para os componentes desse template. Para que isso ocorra, nós precisamos definir um objeto que contém propriedades e métodos que serão utilizadas no nosso jogo-da-forca. Observe o exemplo abaixo.

var Hangman = (function() {
    // Initializing self
    var self = {};

    var template = `${ /* Our template here */ }`
});
Enter fullscreen mode Exit fullscreen mode

Perceba que declaramos uma variável chamada “self” e atribuímos a ela um objeto vazio. Esse objeto conterá as propriedades e métodos que serão utilizados pelo nosso jogo.

O nome self é uma convenção, mas fica a seu critério o nome de variável que você quiser colocar.

O Lemonade possui três métodos principais:

lemonade.element(t, self);
lemonade.render(o, el, self);
lemonade.blender(template, self, el);
Enter fullscreen mode Exit fullscreen mode
  1. lemonade.element - Recebe uma template e um self, aplicando as proprieades do self na template e retornando-a em forma de DOM.
  2. lemonade.render - Renderiza um elemento DOM “o” em um elemento DOM “el”, utilizando o objeto “self” especificado para fazer um binding de suas propriedades e métodos.
  3. lemonade.blender - É uma junção do lemonade.element com o lemonade.render, este método atribui um objeto “self” à um template, interligando suas propriedades, e em seguida renderiza o template em um elemento DOM “el”.

Se você ficar confuso agora, não se preocupe, esses conceitos serão abordados várias vezes enquanto desenvolvemos o nosso jogo.

Renderização da template

Agora que temos uma template definida e conhecemos os principais métodos do Lemonade, podemos renderizar nosso template já definido na nossa página HTML. Lembre que no nosso arquivo HTML temos um div container com um id “root”. Ele será o container que escolhemos para renderizar o template.

var Hangman = (function() {
    // Initializing self
    var self = {};
    // Define our game template
    var template = `${ /* Our template here */ }`


    return lemonade.element(template, self);
});
Enter fullscreen mode Exit fullscreen mode

Na última linha de código, nós retornamos o resultado do método element do Lemonade. Como visto anteriormente, o método element recebe o template e o nosso self, aplicando os atributos e métodos do nosso self ao template e retornando-o como um elemento DOM.

Para ver isso funcionando precisamos fazer uma chamada para o método render do lemonade.

var Hangman = (function() {
    // Initializing self
    var self = {};
    // Define our game template
    var template = `${ /* Our template here */ }`


    return lemonade.element(template, self);
});

lemonade.render(Hangman,document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

Com isso, estamos passando o container div com o id “root” da nossa página HTML como container para nosso template. Até este ponto, você verá este resultado:

Alt Text

Este é nosso template inicial do nosso jogo-da-forca, agora podemos começar de fato a parte divertida, as funcionalidades do nosso jogo!

Definindo as propriedades do self

Para começar, precisamos definir algumas propriedades no objeto self que serão utilizadas durante o ciclo de vida do nosso jogo.

var Hangman = (function() {
    // Initializing self
    var self = {};
    // Property to store the number of user fails
    self.fails = 0;
    // Property to store the last user input 
    self.userInput = '';
    // Property to be a clue of the word
    self.clue = 'FRUITS';
    // Property to store a random word of self.values
    self.currentWord = '';
    // Property to be used to apply some changes in the selected 
    // current word
    self.auxWord = '';
    // Property to store all the possibilities of words
    self.values = ['apple', 'banana', 'orange', 'pear', 'papaya', 
       'kiwi', 'lemon', 'mandarine', 'peach', 'raspberry', 
       'mango', 'fig', 'plum'];
    // Property to store the element where the letters are
    self.lettersElement = null;


    var template = `${ /* Our template he re */ }`;

    lemonade.element(template, self);
});
Enter fullscreen mode Exit fullscreen mode

Para melhor entendimento, vamos fazer uma breve análise sobre cada propriedade que acabamos de adicionar ao objeto self.

  1. self.fails - Armazenará o número de falhas cometida pelo player, será usada como controle de vitória / derrota no jogo.
  2. self.userInput - Armazenará o input atual do player, será necessário para fazer validações durante o jogo.
  3. self.clue - Armazenará a dica atual do jogo, no jogo que estamos desenvolvendo, escolhemos a dica “FRUITS” como padrão.
  4. self.currentWord - Armazenará uma palavra sorteada do array em self.values, a cada rodada em nosso jogo nós geramos uma nova palavra.
  5. self.auxWord - Essa é uma propriedade de controle. Ela sempre terá o valor de self.currentWord e a usaremos futuramente para fazer validações entre o input do usuário e a palavra atual do jogo.
  6. self.values - Armazenará um array com todas as possíveis palavras que nosso jogo pode ter. Como padrão, iniciamos definindo um conjunto de 13 palavras diferentes, para o tema padrão frutas.
  7. self.lettersElement - Armazenará o container que é responsável por fazer o display das letras no nosso template.

Uma vez que temos as principais propriedades que serão utilizadas no nosso jogo, vamos utilizar uma delas, a propriedade clue do objeto self. Vamos no nosso template, e onde temos

<span>Clue:</span>
Enter fullscreen mode Exit fullscreen mode

Vamos alterar para

<span>Clue: {{ self.clue }}</span>
Enter fullscreen mode Exit fullscreen mode

Com isso feito, nós iremos observar a primeira mágica do Lemonade:

Alt Text

Perceba que o valor atribuído à propriedade clue do objeto self foi renderizado no span através da sintaxe { { self.clue } } , gerando o resultado clue: FRUITS como visto na imagem.

Esse é o primeiro passo para o entendimento do Lemonade! Agora que você sabe como acessar valores de propriedades do objeto self no seu template, podemos prosseguir.

Definindo métodos do jogo

Método setWord

Para continuar o desenvolvimento do jogo, precisamos de um método que sorteia uma palavra aleatória de acordo com nosso array definido em self.values. Para isso, adicione uma propriedade chamada setWord ao seu self com a seguinte lógica:

self.setWord = function() {
        self.currentWord = self.values[Math.floor(Math.random() * 
                            self.values.length)];
        self.auxWord = self.currentWord;
}
Enter fullscreen mode Exit fullscreen mode

Como já dito anteriormente, este método está fazendo apenas duas coisas:

  1. Sortear uma palavra aleatória do array self.values e atribuí-la à propriedade currentWord do nosso self.
  2. Atribuir a palavra gerada anteriormente à propriedade auxWord do nosso self.

Método renderLetters

Concluindo o método anterior, agora podemos observar outra funcionalidade do Lemonade! Para isso, vamos criar um método que será responsável por fazer o display das letras da palavra sorteada em nosso jogo. Adicionaremos uma propriedade ao nosso self com o nome renderLetters, inicialmente com escopo vazio.

// Render elements which will be the slots for each letter
self.renderLetters = function(o) {

}
Enter fullscreen mode Exit fullscreen mode

Você pode se questionar o porquê de termos atribuído um parâmetro “o” no nosso método. Aqui entra a magia do Lemonade, vamos voltar no nosso template e adicionar os seguintes atributos na nossa div com classe “word”.

<div class='word' @ready='self.renderLetters(this)' @ref='self.lettersElement'></div>
Enter fullscreen mode Exit fullscreen mode

O que acabamos de fazer? Nós aqui introduzimos dois atributos do Lemonade ainda não explorados: @ready e @ref.

  1. @ready - Este atributo Lemonade pode ser adicionado a qualquer elemento HTML, e seu objetivo é basicamente executar algum procedimento quando o elemento referenciado por @ready está totalmente renderizado.
  2. @ref - Cria uma referência no nosso objeto self para o elemento apontado por @ref. No exemplo acima, por exemplo, estamos adicionando à propriedade lettersElement do nosso self uma referência para a div com classe “word”.

Uma vez entendido os conceitos acima, nós temos garantia que, quando este elemento for totalmente renderizado, ele chamará nosso método renderLetters, e que agora possuímos uma referência para este elemento através da propriedade lettersElement.

Perceba também que no atributo @ready nós passamos como argumento a palavra-chave this. O this é exatamente o elemento que o @ready aponta. Tendo isso em vista, agora sabemos que o parâmetro “o” definido no nosso método em renderLetters será o elemento apontado por @ready.

Após o entendimento de todos os conceitos vistos anteriormente, podemos continuar com a implementação do método renderLetters.

self.renderLetters = function(o) {
    // First we'll clear up the element
    o.innerHTML = '';
    // Setting a random word in our array of fruits 
    self.setWord();
    // Loop to create each letter element
    for (var i = 0; i < self.currentWord.length; i++) {
        var letterElement = document.createElement('span');
        o.appendChild(letterElement);
    }
}
Enter fullscreen mode Exit fullscreen mode

Vamos entender o que fizemos aqui. Primeiro nós limpamos o conteúdo interno do nosso elemento “o”, que como visto anteriormente é o container que armazena as letras da palavra sorteada em nosso jogo.

Após isso, nós chamamos self.setWord para sortear uma palavra aleatória do array em self.values e atribuí-la à propriedade currentWorld do nosso self.
Em seguida, fazemos um for loop com uma quantidade de iterações igual ao número de caracteres que a palavra sorteada tem, por isso iteramos de zero à self.currentWord.length.

Este for loop cria os slots correspondentes a cada letra da palavra, representados pela tag “span” e armazena-os no container “o”. Veja um dos resultados abaixo:

Alt Text

Legal! Agora nosso jogo-da-forca está começando a tomar forma.

Método showLetter

Uma vez implementado o método que renderiza os slots das letras da palavra sorteada, agora precisamos de um método que faz o display da letra digitada pelo player caso ela exista na palavra sorteada.

Queremos o seguinte comportamento: Imagine que a palavra sorteada é BANANA, e o usuário digita a letra “A”, sabemos que essa palavra geraria 6 slots de letras, então o resultado esperado seria: _ A _ A _ A.

Para isso, precisamos implementar um método que mostre todas as correspondências de letra de acordo com o input do player. Observe a implementação do método abaixo:

self.showLetter = function(letter) {
    for (var i = 0; i < self.currentWord.length; i++) {
        if (self.currentWord[i] == letter) {
            self.lettersElement.children[i].textContent = letter;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Neste método, nós estamos fazendo um loop que itera sobre todo caractere da palavra sorteada (armazenada em self.currentWord) e verificando as correspondências com a letra digitada pelo player.

Caso tenha alguma correspondência, pegamos o slot correspondente da letra através de self.lettersElement.children[i] e atribuímos a letra ao seu conteúdo de texto.

Método showStickman

Nosso próximo método será responsável por mostrar as partes do corpo do nosso hangman de acordo com as ações do player. Caso o player digite uma letra que não existe na palavra sorteada, uma parte do hangman deve ser mostrada, e caso o hangman seja mostrado por completo, significa que o player perdeu o jogo.

Observe a implementação do método abaixo:

self.showStickman = function(body_id) {
    document.getElementById('stickman-' + 
     body_id).style.visibility = 'visible';
}
Enter fullscreen mode Exit fullscreen mode

Para entender o que fizemos, você precisa se lembrar que o nosso hangman é um SVG que possui seus membros (braços, pernas, corpo e cabeça) definidos por tags “path”, e cada uma dessas tags possui um id correspondente, observe:

<path id="stickman-1" ...></path>
<path id="stickman-2" ...></path>
<path id="stickman-5" ...></path>
<path id="stickman-6" ...></path>
<path id="stickman-3" ...></path>
<path id="stickman-4" ...></path>
Enter fullscreen mode Exit fullscreen mode

Nós temos a seguinte correspondência entre cada path e parte do hangman:

  1. stickman-1 - cabeça
  2. stickman-2 - corpo
  3. stickman-3 - braço esquerdo
  4. stickman-4 - braço direito
  5. stickman-5 - perna direita
  6. stickman-6 - perna esquerda

Voltando na implementação do método, observe que nós esperamos por um parâmetro “body_id”, que será justamente um numero de [1 - 6], pegamos uma dessas partes de acordo com o id da parte do corpo e mudamos a propriedade “visibility” dela para “visible”.

Método check

Não fizemos testes com os métodos “showLetter” e “showStickman” implementados anteriormente porque eles eram métodos necessários para a implementação do método check.

O método check terá a função de gerar o comportamento do jogo de acordo com o input do player. Vamos iniciar a implementação:

self.check = function(o) {
    self.userInput = o.value;
}
Enter fullscreen mode Exit fullscreen mode

O nosso intuito aqui é gerar interatividade de acordo com a letra digitada pelo player, portanto, criaremos uma maneira de chamar a função check sempre que o player digitar uma letra. Vá no seu template e adicione as seguintes mudanças em

 <input type="text" name="user-input" placeholder="Enter a letter" 
   onkeyup="self.check(this)"/> 
Enter fullscreen mode Exit fullscreen mode

Nós adicionamos um atributo “onkeyup” ao input, criando um evento do tipo keyup que irá disparar sempre o método check do nosso self. Passamos “this” como argumento, e nesse contexto, “this” sempre será o elemento associado ao evento, ou seja, o input.

Voltando no código do método check, na primeira linha nós atribuímos à self.userInput o valor de o.value, acredito que agora isso faça sentido para você, pois como visto anteriormente, o “o” será o input do template, e acessando sua propriedade value, obtemos o texto atual no input.

O que está acontecendo de forma resumida é:

  1. Ao apertar uma tecla no input, o evento onkeyup é disparado, chamando o método check do nosso self.
  2. Atribuímos à propriedade userInput do nosso self o valor atual do caractere digitado pelo player.

Vamos continuar com a implementação do método check:

self.check = function(o) {
    self.userInput = o.value;
    // Checking if the user input is in the current word
    var findedLetterIndex = self.auxWord.indexOf(self.userInput);
    // Check if the user input exists in the current game word
    if (findedLetterIndex >= 0) {
        self.auxWord = self.auxWord.replaceAll(self.userInput, 
         "");
        self.showLetter(self.userInput);
    }
}
Enter fullscreen mode Exit fullscreen mode

Lembra que quando chamamos o nosso método setWord, atribuímos a palavra sorteada tanto a self.currentWord quanto a self.auxWord ? É aqui que utilizaremos a palavra auxiliar, para que possamos fazer alterações nela sem perder referência para a palavra sorteada atual.

Temos uma condicional que verifica se a letra digitada pelo player existe na palavra sorteada. Para essa condição temos duas possibilidades:

  • Existem ocorrências do input do player na palavra sorteada
  • Não existem ocorrências do input do player na palavra sorteada

Para a primeira situação, nós removemos todas as ocorrências dessa letra na palavra e fizemos o display nela através do método showLetter, passando o userInput atual.

Caso contrário, nós temos a seguinte implementação:

self.check = function(o) {
    self.userInput = o.value;
    // Checking if the user input is in the current word
    var findedLetterIndex = self.auxWord.indexOf(self.userInput);
    // Check if the user input exists in the current game word
    if (findedLetterIndex >= 0) {
        self.auxWord = self.auxWord.replaceAll(self.userInput, 
         "");
        self.showLetter(self.userInput);
    }else {
        // Handles user fails 
        self.fails++;
        self.showStickman(self.fails)
    }
}
Enter fullscreen mode Exit fullscreen mode

Nós adicionamos o desvio condicional “else”, que indica a segunda situação vista anteriormente.

Para a segunda situação, nós precisamos incrementar a quantidade de falhas cometidas pelo player e chamamos o método implementado anteriormente showStickman passando como argumento o número de falhas.

Lembre-se que o método showStickman do nosso self recebe como argumento um “body_id”, e mostra a parte do corpo do hangman de acordo com este body id. Este é o motivo pelo qual passamos self.fails como parâmetro.

Método endGame

De acordo com a quantidade de acertos ou falhas do player, em um momento o jogo vai acabar. Portanto precisamos definir um método que lide com isso. Criaremos o método “endGame” que será uma propriedade do nosso objeto self.

self.endGame = function(o, m) {
    o.setAttribute('disabled', '');
    var message = !m ? "You finished the game successfully, 
                   congratulations" : "You failed! Try again?";
    alert(message);
}
Enter fullscreen mode Exit fullscreen mode

Nosso método será simples, mas tratará duas possibilidades:

  • O player conseguiu acertar todas as letras da palavra sorteada a tempo.
  • O player não conseguiu acertar todas as letras da palavra sorteada a tempo.

Parametros:

  • o - Será o input de usuário, ele será desabilitado sempre que o usuário ganhar ou perder o jogo.
  • m - Terá dois valores possíveis, zero e um. Se “m” for zero, significa que o usuário conseguiu finalizar o jogo, se for um, significa que o usuário perdeu o jogo.

No final do jogo, ocorrerá o display da mensagem escolhida pelo parâmetro “m” através do comando alert. Simples assim.

Finalizando o método check

Para finalizar o método check, precisavamos da implementação do método endGame feita anteriormente, agora podemos definir a lógica de vitória / derrota do nosso jogo-da-forca. Observe o código fonte:

self.check = function(o) {
    self.userInput = o.value;
    // Checking if the user input is in the current word
    var findedLetterIndex = self.auxWord.indexOf(self.userInput);
    // Check if the user input exists in the current game word
    if (findedLetterIndex >= 0) {
        self.auxWord = self.auxWord.replaceAll(self.userInput, 
         "");
        self.showLetter(self.userInput);
        if (! self.auxWord.length) {
            self.endGame(o, 0);
        }
    } else {
        // Handles user fails 
        self.fails++;
        self.showStickman(self.fails)
        if (self.fails > 5) {
            self.endGame(o, 1);
        }
    }
    // Reset the input value
    o.value = "";
}
Enter fullscreen mode Exit fullscreen mode

Nós adicionamos os seguintes trechos de código:

if (! self.auxWord.length) {
    self.endGame(o, 0);
}
Enter fullscreen mode Exit fullscreen mode

Esta condicional está verificando se a propriedade auxWord do nosso self não possui mais nenhum caractere, caso isso seja verdade, significa que o usuário finalizou o jogo com sucesso, então chamamos self.endGame passando como parâmetro o input para “o” e zero para “m”.

if (self.fails > 5) {
    self.endGame(o, 1);
}
Enter fullscreen mode Exit fullscreen mode

Esta condicional verifica se o número de falhas é superior a cinco. Caso isso seja verdade, significa que o player atingiu o número máximo de erros e fez o hangman ser enforcado. Em seguida chamamos self.endGame passando como parâmetro o input para “o” e um para “m”.

o.value = "";
Enter fullscreen mode Exit fullscreen mode

E no final, após todas as verificações, limpamos o conteúdo do input, atribuindo o valor dele à uma string vazia. Fazemos isso porque queremos garantir que o player só digite um caractere por vez.

Veja o resultado do que fizemos até agora:

Alt Text

O jogo já está funcionando! Muito legal, né? Agora só precisamos definir a funcionalidade de restart do jogo.

Método resetGame

O método resetGame será uma propriedade do nosso objeto self que reinicializará algumas propriedades de controle definidas no nosso self.

self.resetGame = function() {
    // Restarting the main properties
    self.fails = 0;
    self.userInput = '';
    self.currentWord = '';
    self.auxWord = '';
    self.lettersElement = null;
    // Cleans the entire container
    document.getElementById('root').innerHTML = '';

    lemonade.blender(template, self, 
      document.getElementById('root'));
}
Enter fullscreen mode Exit fullscreen mode

A parte mais importante deste código é o lemonade.blender, onde novamente passamos o nosso template, o nosso self e o container. Isso fará com que o Lemonade reaplique o self, com as propriedades reiniciadas ao template, e renderize-o no container que escolhemos. Perfeito e simples, não?

Agora precisamos interligar a chamada dessa função com o evento de clique no botão de restart. Para fazer isso, na nossa template, adicione o seguinte código no elemento abaixo:

<input type="button" onclick='self.resetGame()' value="Restart Game" />
Enter fullscreen mode Exit fullscreen mode

Finalização e agradecimentos

Parabéns por ter chegado até aqui, agora você tem uma boa noção de como o Lemonade funciona.

Para visualizar o resultado final, Clique aqui

Lembre-se de visitar o site do LemonadeJS

Top comments (0)