Antes de me perguntar alguma coisa - sobre alguma dúvida técnica, algum problema que você está tendo - por favor, leia o texto abaixo. Não sou um cara muito chato, creio. Nem sou consultor que cobra por hora. Acredito que a informação e o conhecimento devem ser compartilhados tanto quanto possível. Por causa disso, quando alguém me pergunta algo ou tá com algum problema no ActionScript, eu geralmente tento ajudar. No entanto, isso tem se tornado cada vez mais difícil. Não pelos problemas em si - sinceramente, no tipo de trabalho que tenho de fazer já me deparei com provavelmente 99.8238% dos problemas possíveis de serem encontrados no Flash - mas porque a descrição do problema pra mim tem se mostrado extremamente deficiente em boa parte das vezes. Se alguém me faz uma pergunta e eu não entendi qual o problema, não vou saber a solução. Isso pode ser frustrante pra quem faz a pergunta, mas é muito mais frustrante pra mim porque me faz parecer um imbecil quando sou obrigado a dar soluções - chutes - que não têm nada a ver com o problema. Pra evitar esse tipo de situação, aqui vai um texto que, espero, ajudará *você* a entender direito seu problema - quem sabe até resolvê-lo - antes de me perguntar algo (ou pra qualquer outra pessoa que saiba mais do que eu). Não leve pro lado pessoal. Esse texto não foi inspirado por uma pessoa ou mensagem específica. Ele é o amálgama de vários problemas com que me defrontei na vida real, através de emails, através de fórums, através de icq, através de msn; este texto é pra te ajudar. Além disso, o texto está escrito de uma forma direta e sem rodeios. Se você é do tipo que se ofende facilmente, bom, você nunca deveria ter me conhecido. ================================================================================ 1. Entenda seu problema. -------------------------------------------------------------------------------- Ok, você está tentando fazer algo. E esse algo não está funcionando. Legal. O que você deve fazer agora, é entender exatamente *o que* não está funcionando. Digamos que tenhamos uma linha de execução: <---------------------------------------------------------------------------> Começo do programa Programa funcionando Pra partir de um exemplo mais prático: <---------------------------------------------------------------------------> Começo do programa Carregar e mostrar uma imagem O intuito de todo programa/movie/swf/código etc é funcionar do começo ao fim. Se ele não funciona, existe algum problema no meio. Não pense no seu problema como "estou tentando carregar uma imagem, mas isso não funciona". Seu problema, ao invés, pode ser algo como "estou tentando carregar uma imagem, mas a imagem sendo carregada é um JPEG progressivo, que o Flash não suporta" ou "estou tentando carregar uma imagem, mas ela está sendo carregada num nível invisível". Digamos que o código de nosso exemplo seja esse: myMovie.createEmptyMovieClip("imagem", 10); myMovie.imagem.loadMovie("fnord.jpg"); Pra chegar à raiz do problema, você deve debugar - ou depurar - seu código. Isso se faz criando "pontos de checagem" do meio do código pra verificar se ele está fazendo o que deveria estar fazendo. <---------------------------------*-----------------------------------------> Começo do programa Checar algo Carregar e mostrar uma imagem Imagina aquele lance: você tem de descobrir um número de 1 a 1000 que alguém pensou. O que você faz? Vai por força bruta, ditando todos os números de 1 a 1000, até acertá-los? Não, você escolhe um número no meio (digamos, 500), e checa com a pessoa se está correto, ou se o número correto é maior ou menor. Se for menor que 500, você checa o número 250, e assim por diante. É mais rápido, e é exatamente assim que a depuração funciona: estabelecendo pontos ou "checkpoints" no meio do seu código, você descobre exatamente o que está errado, e como corrigir. Esse é uma das principais habilidades usadas em programação, e não existe bug ou problema que resista a isso. Se você não sabe depurar direito, aprenda ou mude de profissão. Boa programação não depende só do conhecimento sintático de uma linguagem - isso se consegue através de uma referência de qualquer forma - mas também da capacidade de escrever código conciso e depurar problemas. (PS: embora eu tenha falado "checkpoints", não, eu pessoalmente não uso os checkpoints do Flash, nem o debugger -- só uso traces. Isso é uma decisão pessoal e não quer dizer que tenha de ser assim). Lembre-se do código que usei no exemplo anterior: myMovie.createEmptyMovieClip("imagem", 10); myMovie.imagem.loadMovie("fnord.jpg"); Digamos que o código não esteja funcionando, ou seja, você não esteja vendo imagem alguma. Ótimo. Existe uma gama infinita de problemas que poderia estar causando esse funcionamento errôneo. Não dá pra sair adivinhando - através de força bruta - tudo que pode estar acontecendo. O que você tem de fazer primeiro é estabelecer um ponto de checagem, pra tentar diminuir restringir essa faixa de problemas a alguns problemas mais específicos. Isso é feito geralmente através da checagem de valores de variáveis no meio do código, pra ver se elas estão se comportando como deveriam. Por exemplo: myMovie.createEmptyMovieClip("imagem", 10); trace ("imagem -> "+myMovie.imagem); myMovie.imagem.loadMovie("fnord.jpg"); O que esse código faz é dar um trace do movieclip que foi criado pra conter a imagem. Uma das saídas possíveis é: undefined Ou seja, o movieclip não foi encontrado - ele não existe. Isso quer dizer que o movieclip "imagem" não pôde ser criado no movieclip "myMovie", ou seja, o problema não é do loading da imagem em si. Pode ser, ao contrário, que o nome "myMovie" esteja escrito errado, ou a referência não exista. Outra saída possível: _level0.myMovie.imagem Isso quer dizer que o movie existe, então o problema é no loading. Pode ser que o arquivo de imagem não exista, ou que seja um JPEG progressivo. Ou mesmo que o myMovie esteja escondido. Em ambos os casos, você tem de continuar checando até encontrar o problema mais específico. Formule o problema corretamente em sua mente. Só assim você vai poder passá-la pra outra pessoa. ERRADO: Tá dando erro no meu código. O que é? OU Minha imagem não carrega. O que é? CERTO: Estou tentando carregar uma imagem num movieclip, mas a imagem não está sendo mostrada. O movieclip existe corretamente e está visível e com _alpha 100. O que pode ser? Outros exemplos: ERRADO: Não consigo setar o texto do textfield. O que é? CERTO: Tenho um textfield tal em tal lugar, e estou tentando setar o texto dele com o código tal. No entanto, isso só está apagando o texto já existente no movieclip. O que pode ser? -- ERRADO: Meu textfield não mostra nada. O que é? CERTO: Meu textfield está numa máscara e o texto não é mostrado. Quando movo ele pra fora da máscara, ele funciona. O que pode ser? Etc. ================================================================================ 2. Programe direito -------------------------------------------------------------------------------- É, isso parece óbvio. Mas tenho percebido que a raiz de muitos problemas - ou o principal obstáculo pra solução de muitos problemas - tem sido o código mal escrito: funções e loops macarrônicos, escopos totalmente esquizofrênicos, coisas que funcionam mas que estão na corda bamba prestes a explodir. Não pretendo ensinar ninguém a programar direito com um texto simples, afinal eu mesmo tenho uma caralhada de coisas pra aprender ainda. No entanto, o que eu quero dizer é que se você fizer seu código de forma *SIMPLES*, vai não só ajudar a si mesmo, mas ajudar a quem for tentar resolver seu problema. Nos últimos anos, eu tenho tentando otimizar a lógica que uso em meu código exatamente pra poder resolver os problemas que surgem de forma simples e direta. Vocês não imaginam como é frustrante me deparar com um código cheio de nós do nada, e tentar enxergar no código o que nem quem o criou consegue. Um bom programador não é o programador que fica seguindo trilha do código pra entender o que tava se passando pela cabeça de quem escreveu aquilo, mas sim o cara que escreve um código que faça sentido não só pra ele mas também pro resto do mundo. * SIMPLIFICAÇÃO Quando eu digo "de forma simples", não quero dizer "de forma retardada". Eu quero dizer, na verdade, de uma forma que faça sentido, de uma forma que seja lógica. Teve um artigo escrito pelo Linus Torvalds (quem criou o linux) sobre programação onde o cara falava algumas 'guidelines' de lógica de programação. Não lembro direito nem tenho o link disso, mas o cara falava coisas como "se sua função tem mais do que uns 3 blocos aninhados (if/while/for/etc) ela já tá errada, deveria ser dividida em funcões menores". "Se tem mais do que 20 linhas na função, divida-a em funções menores". Coisas assim. Isso é um pouco xiita na minha opinião, mas a verdade é que simplificações desse tipo realmente ajudam. Se você tem um bloco de 500 linhas de código com 20 níveis de profundidade, vai ser foda paca atualizar isso. Não espere entender esse seu próprio código daqui a 6 meses. * ATALHOS O Actionscript aceita dois 'tipos' de variáveis: variáveis com valores *absolutos*, como um número ou uma string, e variáveis de objetos, que possuem *referências* (sei lá o nome correto/oficial desses negócios, estou falando como eles são na prática). Valores 'absolutos' são passados de variáveis pra variáveis como valores mesmo. Exemplo: var a = 1; var b = a; var a = 2; trace (b); // Mostra "1" 'Referências', ou atalhos, ou shortcuts, são usados em objetos mais complexos - arrays, movieclips, objetos. Eles são passados como referência, isto é, se você muda o original, o novo também se modifica. Não é uma cópia, só um 'link' pro original. Exemplo: var a = _root; _root.coisa = "COISA!"; trace (a.coisa); // Mostra "COISA!" Referências são suas amigas. Elas simplificam a leitura do código pra caralho e devem ser usadas sempre que possível (e não mais do que isso). Por exemplo, isso: this.myMovieClip.duplicateMovieClip("item_"+i, i); this["item_"+i]._x = 10; this["item_"+i].gotoAndPlay(2); Pode virar isso: var im = this.myMovieClip.duplicateMovieClip("item_"+i, i); im._x = 10; im.gotoAndPlay(2); Esse é um caso menor, mas acredite que existem casos em que referências como essa ajudam em muito a leitura do seu código. E se você precisa de algum outro motivo, ajuda também a tokenização de seu código (o swf fica menor) e a rapidez de processamento. Em ambos os casos de forma marginal.. mas ajuda. Outra coisa: caso o atalho seja apagado, o objeto original continua existindo. Só a referência a ele é perdida. * ESCOPO ESCOPO refere-se à 'área' do movie onde um certo código está sendo executado... dentro de um movieclip, de uma função, etc. Esse é um caso mais complexo, difícil de explicar num texto tão pequeno. Recomendo que leiam o livro ASDG2 do Colin Moock pra entender melhor, mas basicamente: "var" é usado pra criar variáveis dentro de funções. Use-as pra variáveis temporárias - elas são apagadas depois que a função é executada. Quando criadas na timeline, no entanto, elas continuam existindo. "this." faz referência ao movieclip onde a função está sendo executada. Use-o. objetos/variáveis/propriedades sem "this." ou que não foram criados com "var" referem-se ao escopo de onde a função está sendo executada. O caso, no geral, é que você tem de tomar cuidado ao usar variáveis sem referência nenhuma. Elas ficam 'perdidas' no tempo e espaço, e embora possam funcionar numa boa a partir de determinado ponto, você terá problemas ao chamar funções de outras áreas de seu código, e se acostumar com esse tipo de prática pode levar a sérios erros de lógica no seu código, se você não tiver certeza do que está fazendo. Assim, eu pessoalmente sempre gosto de deixar meu escopo CLARO pra não ter de depender da ordem da chamada scope chain pro meu código funcionar. Evite isso: i = 10; myMovie.doSomething = function() { trace ("i é "+i); }; É um lixo porque, embora funcione, você vai estar dependente do valor do i original toda hora. Se você acha que você pode fazer isso num loop - erro clássico depois de perceber que o código acima funciona - esqueça, todas as funções teriam o mesmo valor de i. Isso, no entanto, é 'mais correto': i = 10; myMovie.i = i; myMovie.doSomething = function() { trace ("i é "+this.i); }; Ou, ainda, se você realmente quer o valor original: this.i = 10; myMovie.doSomething = function() { trace ("i é "+this._parent.i); }; * REGRINHAS Não existem 'regrinhas' a serem seguidas para actionscript. Mesmo o que falei são conselhos pessoais. Quem segue cegamente regrinhas do tipo "coloque todo o código do swf num mesmo frame" (a pior que já vi) está fazendo um desserviço a si mesmo. Aprenda, tente, erre e acerte: só a experiência vai dizer o que funciona direito. Não tenha medo de ir contra regrinhas que você ouviu em algum canto: nenhuma regrinha pode ser seguida à risca. Já vi merdas tão grandes escritas em livros e artigos por aí que me deixam de queixo caído. Ou eu sou burro demais, ou tem enganador demais por aí. Ou, às vezes, são regrinhas que fazem sentido dentro de algum contexto mas as pessoas acabam extrapolando e usando-as sempre ou em lugares bizarros. Não são regrinhas que farão seu código ou seu Flash ficar melhor. É saber o porque de cada regrinha, ou de cada sugestão, e usá-las onde fizer sentido. PS: Você não programa pra si mesmo. Programa pra si mesmo daqui a um ano, programa pra outra pessoa que vai ler seu código mais pra frente. Se quiser escrever seu código em uma linha cheio de funções não documentadas e usando truques que aparentemente não funcionam, ótimo: vai funcionar, mas vai ser um código de manutenção impossível, e instável (dependente de peculiaridades da versão atual do player e compilador). Isso não indica o bom programador. Bom escritor não é aquele que escreve um parágrafo em 1 cm cúbico, e nem aquele que faz garranchos ilegíveis. É aquele que escreve de forma que o leitor entenda - no caso do programador, aquele que vai mexer no código no futuro entenda; às vezes, ele mesmo. ================================================================================ 3. Pense antes de fazer -------------------------------------------------------------------------------- Ok, esse é um assunto muito maior, juro que ainda vou escrever um livro sobre o assunto. Mas tenho algumas teorias sobre o Flash e como ele lida com seu conteúdo... O Flash é uma ferramenta super bizarra. Pra qualquer coisa que você quer criar nele, tem 100 formas de fazer.. indo da mais simples e rápida, até a mais burocrática e organizada; da mais manual e oldschool, até a mais dinâmica e programada. Isso porque o Flash evolui de uma ferramenta de animação e scripting tosco pra uma ferramenta que permite programação orientada a objetos bastante complexa. Não existe regra geral pra definir o que deve ser feito, de que forma, com o quê.. Existem, digamos, algumas convenções, que podem ser adotadas, mas isso vem muito da experiência de cada um e depende do tipo de trabalho. Algumas coisas devem ser feitas de uma forma simples e rápida. Formas simples e rápidas são legais, mas modificá-las no futuro pode ser um grande problema. Dá pra matar um tigre com um alfinete, mas vai ser um trabalhão. Algumas coisas devem ser feitas de forma super organizada, estruturada. Isso é bom, mas se o trabalho é algo pequeno, não tem sentido gastar uma semana de planejamento pra criar uma classe cheia de métodos só pra mostrar um número randômico na tela. É o equivalente a plantar uma árvore, esperá-la crescer, serrá-la, mineirar e fundir um pouco de metal, e usar isso pra construir um martelo que vai ser usado pra matar uma formiga. Dá pra fazer, mas é tempo e trabalho desperdiçado. Achar o meio termo entre problema e solução - o quanto vale a pena investir no trabalho - é uma das questões sem fim de qualquer projeto de tecnologia, e no Flash eu só vejo isso aumentado a proporções astronômicas graças aos modos estranhos com que as coisas podem ser feitas dentro dele, e graças ao fato de que tem muito novato (ou "enganador" se preferir) mexendo com a ferramenta com a impressão de que um copy&paste de um FLA de alguém já vai fazer tudo por ele. Embora eu não defenda a solução do martelo pra formiga, eu costumo me deparar toda hora com pessoas que optaram pela solução mais simples e rápida pra um problema mas que, no decorrer do desenvolvimento, o problema se transmutou em algo mais complexo, o que fez com que a solução (originalmente simples) se transformasse em um ser totalmente bizarro, um emaranhado de remendos de código. Isso é porque o projeto não foi pensado antes de ser começado, porque a pessoa que o fez achou que pudesse realizá-lo só através da gambiarra, e não contou com a manutenção futura. Não vou falar que sou perfeito. Eu mesmo me deparo toda hora com 'novos recursos' que me obrigam a dar um passo atrás e fazer algo diferente num código que eu já tinha bolado. Toda hora tento fazer algo um pouco diferente também pra ver se dá certo, e é bem comum não dar. O que eu quero dizer é que, ao invés de pular no problema de cabeça, faça um mapa em sua mente do que tem de funcionar, como, e comece a partir daí - ao invés de atacar o problema de frente, tenha consciência da extensão dele toda e ataque por partes. Faça um código facilmente extensível, encapsulado. Pra explicar melhor, eu tenho esse gráfico na minha mente: d 100 | i | f | i | c | u | l | d | a | d | e 0 `--------------------------------------------- tempo de projeto O eixo Y mostra a dificuldade de realização de um projeto - de 0 a 100 - e o eixo X, o tempo de um projeto, a evolução dele. Muita gente tenta fazer as coisas do modo mais fácil, isto é, atacando problema por problema isoladamente. Elas geralmente começam a coisa dessa forma: d 100 | i | f | i | c | u | l | d | ** a | ** d | ** e 0 `**------------------------------------------- tempo de projeto Ou seja, o projeto começa relativamente fácil, e vai ficando difícil conforme progride. Esse é o método gambiarra, ao meu ver. É o modo como 80% dos trabalhos de Flash que eu vejo são feitos. Só que esse não é o jeito certo de fazer as coisas. Pode até funcionar, mas só até certo grau. Qualquer projeto, por maior que seja, pode ser "quebrado" em pedaços menores, que podem ser trabalhados separadamente. O problema de criar coisas sem pensar é que, num determinado ponto do projeto, ele se torna tão monstruoso que o código é catastrófico, de manutenção próxima do impossível, por exemplo... d 100 | *BUM* i | ** f | ** i | ** c | ** u | ** l | ** d | ** a | ** d | ** e 0 `**------------------------------------------- tempo de projeto Tenho pena de algum programador que é chamado pra "resolver" os problemas que o programador original não conseguiu. Mesmo que ele consiga, vai ter perdido 10 anos de sua vida xingando o programador original. Programadores que pensam, no entanto, dedicam alguns segundos iniciais a pensar no problema, e, ao criar uma solução para ele, o fazem de modo que a manutenção futura SEJA possível. Isso exige certa experiência e bom julgamento, por isso, o começo não é tão rápido e fácil quanto o de soluções menores - são criados processos que, embora não sejam imediatamente usados, serão a casca de uma série de recursos no futuro. d 100 | i | f | i | c | u | l | d | * a | * d | * e 0 `*-------------------------------------------- tempo de projeto O tempo mostra, no entanto, que quando a solução é bem pensada, manutenção futura é bem mais simples, menos frustrante; trata-se simplesmente de expandir o que já foi criado, não de adicionar um recurso novo sem tentar quebrar o que já existe e funciona de forma instável d 100 | i | f | i | c | u | l | d | ****************************************** a | * d | * e 0 `*-------------------------------------------- tempo de projeto É algo difícil de perceber - afinal, o 'mercado' Flash é regido mais por 'flasheiros' que aprendem a usar uma técnica do flashkit do que gente preocupada em programar de verdade - mas é algo que está lá e pouca gente vê. Quem ganha trabalhando direito é o programador. Se você está escrevendo algo e o código começa a ficar cada vez mais complexo - mais difícil de entender - é porque existe um erro em sua lógica. Não importa se você está usando AS1 ou AS2 - todo código deve ser 'encapsulado', isto é, o programador não deve ser obrigado a seguir o rastro de 30 funções pra entender o que está acontecendo. ================================================================================ 4. Ajude-me a ajudá-lo (conclusão) -------------------------------------------------------------------------------- Explique seu problema. Entenda-o, antes de tudo. Se eu não conseguir entender o que você quis dizer, vou falar "não entendi" e pronto. Lembre-se de que eu não recebo nada por ajudar, então não vou fazer um esforço sobrehumano pra tentar entender o que está acontecendo, fazendo uma centena de perguntas só pra sacar o que você está tentando fazer. Coisas a fazer: 1. Explique seu problema específico de uma forma concisa que faça sentido pra alguém que não esteve sentado do seu lado enquanto você escrevia o código. 2. Diga-me o que você está *tentando* fazer. Às vezes, um mínimo problema que pintou no código pode ser a indicação de problemas bem mais graves de sintaxe ou algo que você pode fazer de uma forma radicalmente mais simples. Coisas a não fazer: 1. Não me mande código a menos que eu peça. Me mandar uma função de 200 linhas com a esperança de que eu magicamente veja o problema que você não viu não faz muito sentido lógico, não importa quem eu seja. 2. Não se esqueça de que eu trabalho durante o dia: não vou fazer seu trabalho por você, não vou me distrair do meu trampo totalmente para ajudá-lo, nem vou parar o que estou fazendo pra tentar adivinhar o que se passa em sua mente. Coisas que não sou: 1. Adivinho. 2. Onisciente. 3. Infalível. - zeh