quinta-feira, 28 de julho de 2011

MUI: Indexagem em GUI

Eai garotada, venho aqui ensinar como fazer, de um jeito super simples, magias MUI. No final do tutorial tem um mapa demo. Mas deixe para baixa-lo apenas depois do tutorial, tente fazer nossa magia MUI apenas lendo o tutorial. Nesse tutorial você terá que saber sobre variáveis array e sobre memory leaks, coisas importantes para quem quer aprender MUI.

Mas tio Bills o que é MUI?

MUI na teoria significa Multi-Unit Instanceability. Na prática significa qualquer coisa (não apenas magias) que possa ser usada por vários jogadores e unidades, diferentes ou iguais, ao mesmo tempo sem bugar.


     



    E como eu faço isso?
    É muito simples, jovem gafanhoto. Vou te ensinar pelo jeito mais fácil em GUI, a indexagem. Para quem não sabe o que é indexagem, é um jeito organizar dados de forma que você possa recupera-los através de seu index (um numero de referencia). É como se você fizesse uma “matriz” de dados ou uma lista.

    Vendo essa tabela imaginem uma trigger que roda a cada 1 segundo. Toda vez que ela roda ela busca todos os index, do primeiro (1) ao ultimo (3), Fazendo o CASTER[index] causar o DAMAGE_PER_SECOND[index] ao TARGET[index]. Assim quando o index ser 1, o CASTER[1] (Paladin) vai causar DAMAGE_PER_SECOND[1] (30) ao TARGET[1] (Death Knight), quando ser 2 seria... ah, só olhar na tabela.
    E como faríamos para saber qual é o primeiro index, o ultimo e como faríamos a trigger procurar por todos. Para isso usaremos o comando “For”.







      Mais para frente explicarei o "For", caso voce tenha alguma duvida.

      Vamos começar então?
      Para ensinar MUI vou dar um exemplo bem fácil, vamos criar uma shockwave MUI \o/. Eu sei que a shockwave do warcraft já é MUI, mas quero apenas usa-la como exemplo. Para criar uma shockwave totalmente triggered precisaríamos de uma dummy (que seria a wave/efeito), um trigger para inicia-la e também um trigger periodic (que ocorra a cada “0.03” segundos). Sem MUI, precisaríamos apenas de criar algumas variáveis, armazenar alguns dados nas variáveis quando a magia fosse usada, criar a dummy e armazena-la, mandar ativar a periodic, depois a periodic faria a dummy mover. E todos seriamos felizes, mas queremos mais, queremos MUI!


      Tá, e como vai ser em MUI ?
      Seria quase a mesma coisa, apenas teríamos que criar um novo index e armazenar os dados daquela execução da magia em variáveis “array” usando esse novo index.
      Obs: Para o tutorial usarei a sigla SW para referir a shockwave.

      Vamos lá, crie essas variáveis:

      SW_indexCount (Integer – Default Value: 0)
      SW_newIndex (Integer – Default Value: 0)
      SW_MUI_indexExists (Boolean – array – Size: 1)
      SW_MUI_waveCount (Integer – Default Value: 0)
      SW_MUI_Dummy (Unit – array – Size: 1)
      SW_MUI_Distance (Real – array – Size: 1)
      SW_Loop (Integer)
      Obs: outras variáveis vão aparecer no tutorial, tipo TempUnit. Com essas você pode usar alguma que já tenha ou crie elas se precisar.

      Nossa magia vai começar sempre que uma unidade usar a SW. Ops, já ia me esquecendo, crie uma dummy com locust e mude o modelo dela para o míssil da Shockwave, que vou chamar de SW Dummy, e crie também uma magia shockwave (retire todos efeitos e damage). Vamos lá, quando alguém usar a nossa shockwave custom, o trigger criará um novo index e assim armazenaremos todas as informações em nossas variáveis array usando nosso novo index.

         








        Toda vez que a magia for usada, a SW_indexCount vai ganhar +1 e a SW_newIndex guardará esse novo valor de SW_indexCount. Assim, toda que a magia for usada SW_indexCount vai aumentar seu valor, ficando toda vez diferente. Usaremos SW_MUI_indexExists para saber se a index existe (usaremos ela parar fazer a magia acontecer), se ela for true é porque o index existe e está sendo usado. A SW_MUI_waveCount vai contar quantas waves (dummy) estão se movendo ainda, ou seja, quatas SW ainda estão em andamento.
        Continuando nossa trigger, agora armazenaremos nossas informações e criaremos a dummy. Nessa parte uso algumas variáveis extras para adquirir valores e também para pegar um ângulo.














          Como viu usei algumas variaveis extras. É sempre bom que você armazene valores que serão usados mais de uma vez em variaveis temporárias. Pois o computador busca bem mais rápido uma variável do que uma função (Triggering Unit é uma function, por exemplo). Voltando... O “if” no final da trigger serve para ativar a periodic, caso ela esteja off.
          Obs: essa “Shockwave MUI movement” é nossa próxima trigger, crie ela antes de fazer essa parte.


          Criando uma Periodic com Indexagem
          Agora temos que fazer que todas as magias registradas no index de SW_indexCount seja movidas e causem dano nas unidades inimigas. Não vou explicar como se move uma dummy, não estou fazendo tutorial disso.
          Vamos lá, faça uma trigger chamada “Shockwave MUI movement” e desmarque a opção “Initally On”.
          No evento use “Time – Periodic Event”, coloque 0.03. Nenhuma condição.





            Agora faça o resto da trigger:














              Primeiro vou explicar o “for”, talvez tenha gente lendo isso que não entende ainda. O “for” no GUI pode usar Integer A, Integer B ou uma Integer a sua escolha (como no nosso caso). “For each” significa “Para cada”, Para cada inteiro (integer) de 1 até SW_indexCount (numero de index já usados) ele executará as functions no “Loop – Actions”. Ou seja, se a gente já tiver usado 3 indexs, ele executará ... ? 1 vez, 2 vezes, 3 vezes. 1 vez para cada index. A variável SW_Loop que foi nosso integer escolhido irá ter o valor 1 na 1ª execução, 2 na 2ª , 3 na 3ª e etc. Assim podemos buscar todos as informações guardadas nas nossas variáveis array.
              O primeiro “if”, SW_MUI_indexExists[SW_Loop] Equal to True (verdadeiro), serve para saber se o index existe e está sendo usado. Se der false (falso) é porque o index já foi usado, mas não está mais.
              O próximo if é “SW_MUI_Distance[SW_Loop] less than 1500”, se a distancia percorrida pela wave daquele index ainda é menor que 1500 (nossa distancia máxima), o trigger executa o que está dentro de “Then - Actions”. Ou Se a distancia for “maior ou igual” a 1500 executa o que está dentro do “Else - Actions”. Um if sempre executa apenas um bloco (Then ou Else), nunca os dois.
              Se a distancia for menor que 1500 a dummy irá mover mais 50 de distancia, até chegar no máximo (1500). Senão (else) o index dela será marcado que não existe (não está mais em uso), a dummy será destruída e SW_waveCount será subtraído 1. Lembrando que SW_MUI_waveCount conta quantas waves estão ativas no mapa.
              Lá no final temos um “if”, reparem que ele está fora do “for”, ou seja, ele só será executado quando o for (daquela execução do trigger) terminar. Esse for determina, se a SW_MUI_waveCount for igual a 0 (zero), desativa esse trigger (o periodic), pois não tem nenhuma wave ativa. Só precisamos que ela fique “ligada” quando tiver waves. Lembra que quando uma unidade usar nossa SW, se a periodic estiver “off” ela é ligada, lembrou? E pra finalizar SW_indexCount volta pra 0 (zero), pois nenhum index está sendo utilizado, então ele terá novamente o valor inicial.


              Nesse tutorial eu quis explicar apenas o básico de como fazer uma habilidade MUI, vocês podem se esforçar e ainda aprender sobre reciclagem de index. Procurem baixar mapas de magias no Hive WorkShop, geralmente as magias são todas MUI. Aé, caso você ficou com alguma duvida em alguma parte, baixe o Mapa de demonstração e veja nele. Nesse mapa coloquei duas shockwaves, uma MUI e uma não-MUI, para você verem o que pode acontecer quando uma magia não é MUI e ela é executada varias vezes ao mesmo tempo. No mapa as magias não tem cooldown nem mana cost, então usem varias vezes de uma vez cada shockwave e verá o que é ser MUI.


              Espero ajudar alguns com esse tutorial, beijos e abraços do Mano Bills!


              Leia Mais...

              Comentem!

              Caso voce esteja lendo meu blog e tenha gostado ou não gostado do post, poderia comentar algo? Não custa nada e só vai gastar um pouquinho seu teclado. Isso me ajuda à ajudar vocês.

              Grato desde já, volte sempre.

              Leia Mais...

              2ª Aula de vJass - Primeiras Noções

              Bom essa será nossa segunda aula, sugiro que leiam ela como muita atenção.
              Antes de tudo voce deve saber que vJass é "case sensitive", ou seja, letras maiusculas e minusculas fazem diferença. Unit, é diferente de UnIt ou uNiT ou unit ou uniT e etc. Desta maneira os comandos if e loop, por exemplo, só podem ser escritos em letras minusculas senão o compilador irá interpretá-los como variaveis.

              Primeiro Código

              Vejamos esse código escrito em vJass:
              library Exemplo1
               struct MyStruct
                   // Meu primeiro código
                   static method onInit takes nothing returns nothing
                       call BJDebugMsg("Hello World!")
                   endmethod
                endstruct
              endlibrary

              Este codigo exibirá a messagem Hello World! na tela quando seu mapa iniciar.

              Vamos entender o codigo

                  A linha library Exemplo1 cria uma library nomeada Exemplo1. Uma library é como se fosse um bloco de notas com codigos. Por enquanto é apenas isso que voce precisa saber. Caso queira saber mais leia este tutorial que eu fiz. Quando voce quiser terminar sua library, voce deve apenas escrever a linha (vista no final do código) endlibrary. Esta linha é obrigatória, nunca se pode deixar uma library aberta (sem o seu endlibrary).
                  Quando fazemos um código, uma boa idéia é usar comentarios que ajudem a explicar partes dele. No nosso código temos o comentario // Meu primeiro código, viu né? O compilador desconsidera qualquer coisa que esteja escrito depois do // naquela linha.
                  A linha struct MyStruct cria uma struct e nomeia ela de MyStruct. Uma struct é um objeto e como um objeto, ela pode ter varias caracteristicas. Nas proximas aulas voces entenderam melhor. Assim como na library, o compilador precisa saber onde termina sua struct, para isso apenas escreva endstruct depois de escrever os códigos da sua struct.
                  O static method onInit takes nothing returns nothing é nosso method que sempre vai iniciar junto com o mapa. O method onInit (escrito desse jeito, lembre-se do case sensitive) de uma struct sempre será executado quando seu mapa iniciar, sempre deve ser static e takes nothing returns nothing. O termo static vocês entederam mais tarde. A parte takes nothing diz que o method não precisa de nenhuma variavel para ser executado. Quando voce quiser que um method use alguma variável você pode passar o valor dela pra essa function. E returns nothing significa que esse method não retorna nenhum valor. Um method pode retornar um valor (move speed de uma unit, por exemplo) e você pode preferir guardar esse valor em uma variável. O onInit é o nome do method, esse nome pode ser qualquer um. Contando que não se repita ou comece com números. Aé, methods também precisam ser encerrados. Apenas coloque endmethod no final dele.
                  Única coisa que esse código faz é exibir a messagem Hello World!. 
              function BJDebugMsg takes string msg returns nothing
                  Olha ai, essa function (que é quase a mesma coisa que um method) requer uma string: takes string msg. Uma string é um conjunto de caracteres, quem conhece de trigger editor sabe disso. O comando BJDebugMsg exibe a string msg na tela por um minuto. Só!
                  Antes do comando pode ver que tem a palavra call, que significa chamar. Ele que chama/executa o comando. Uma string sempre deve ser escrita entre aspas (" "), sempre. Um exemplo:
              Faz de conta que voce quer mostrar mostrar a messagem Game Over. Então ficaria assim:

              call BJDebugMsg("Game Over")
                  As coisas escritas dentro dos parenteses são os parametros do comando, o takes dela. Quando um comando tem takes nothing você precisa apenas deixar os parenteses vazios.
              Exemplo:

              call CreateTimer() // um comando que cria um countdown timer.
              call CreateTimer // assim daria erro, faltou os parenteses.
              Quando um comando tem algum returns, voce pode preferir guarda o valor do retorno dela. O comando CreateTimer, por exemplo, é takes nothing returns timer. Ou seja ele retorna um timer, um timer que acabou de ser criado. Faz de conta que voce tem uma variável chamada TempTimer e você quer guarda um novo timer nela:

              set TempTimer = CreateTimer()
              // O comando CreateTimer foi chamado e seu valor de retorno
              // foi guardado na variavel TempTimer


              Primeiramente, desculpe pelas aulas serem semanais. Tentarei faze-las em um periodo mais curto. Espero que tenham entendido sobre esse inicio, voce ainda estará confuso, mas é assim mesmo. Logo logo voce estará entendendo a sintexe do vJass.

              Abraços.

              Leia Mais...

              quinta-feira, 21 de julho de 2011

              1º Aula de vJass - INTRODUÇÃO

                  Vamos, nestas lições, aprender os conceitos básicos da linguagem de programação vJass a qual é muito famosa entre os editores experientes de warcraft, devido ao seu poder.

              Leia Mais...

              quarta-feira, 20 de julho de 2011

              Novo Visual

              Modifiquei um pouco o blog, espero que tenham gostado.
              Em breve falarei de um projeto em que estou trabalhando e tambem iniciarei umas lições de vJass.

              Abraços, até a proxima.

              Leia Mais...