Archive for Programação

A síndrome do jogo favorito tem cura?

Em qualquer comunidade de estudantes e desenvolvedores de jogos, é incrível o número de pessoas que desejam criar um MMOG (massive multiplayer Online Game) como sendo seu primeiro jogo. Parece um ímã, uma atração inevitável: a pessoa é iniciante, portanto tem que escolher logo o que há de mais complexo!

Na verdade, isso é bastante natural, tendo-se em vista o fato de que MMOG é o tipo de jogo que agrada um grande número de pessoas hoje. Antes da popularização dos MMOGs, eram os FPS (first person shooters) os jogos considerados de maior sucesso, tanto dentre as escolhas dos iniciantes, quanto dentre os jogadores, seguidos de RTS (real time strategy) e tantas outras siglas, formando uma grande sopa de letrinhas.

A escolha por tais gêneros é movida pelos seguintes argumentos:

  • Trata-se do gênero favorito da pessoa como jogadora e todos sempre ouvem que trabalhar naquilo que se gosta é uma das melhores formas de ser realmente produtivo;
  • Não se sabe ainda a real complexidade que há em cada gênero ainda, então se torna difícil saber o quão complexo será o desenvolvimento;
  • Há também uma certa superestimação acerca de nossas capacidades: em nossos primeiros passos, estamos tão certos de que somos capazes de qualquer coisa, que para nós poderíamos construir o Cristo Redentor usando somente um gigantesco bloco de pedra e uma lixa de unhas!

Entretanto, vale salientar que “grandes fracassos levam a grandes frustrações, mas pequenos sucessos trazem uma grande motivação”. Em outras palavras: é preferível começar-se por um projeto muito mais simples e ir gradualmente avançando a começar por um MMOG, tropeçar e não conseguir levantar-se mais.

Lembro-me de ter feito, em meus primeiros passos, vários demos de jogos diferentes: um “pacman” sem fantasmas a perseguir o jogador, um mini-jogo de corrida, alguns space invaders, etc.

Posteriormente, tudo evoluiu, defini mais claramente a plataforma em que desenvolvo até hoje (a plataforma Flash) e comecei a criar jogos mais sofisticados (que agora sim passei a chamar de jogos!), como jogos de nave no estilo R-Type, jogos de corrida com visão top down, jogos de cartas, etc.

Bem, aonde estou hoje? Meus últimos projetos foram vários tipos de jogos de tabuleiro, jogos multiplayer como Buraco, Damas, Botão e Texas Hold’em Poker e o meu último projeto já se encaixa melhor na definição de MMOG, uma vez que se trata de um mundo persistente onde jovens podem construir seu avatar e interagir com outros usuários, seja por meio de jogos, seja por meio de atividades sociais.

Quanto tempo levou para ir “de uma ponta a outra”? Cerca de 12 anos, num processo bastante gradual que, apesar de aparentemente lento, para mim foi mais do que satisfatório – motivo pelo qual sempre recomendo fazer o mesmo, “devagar e sempre”.

E se você deseja fazer a mesma coisa, há algumas poucas coisas que podem ser feitas para acelerar um pouco o processo de aprendizado:

  • Comece pelo mais simples e aumente a dificuldade aos poucos! Você descobrirá que aquele snake game que você achava tão bobo enquanto jogador não é tão fácil assim de criar, no fim das contas, e aprenderá muito com isso;
  • Um bom livro vale mais que 1000 artigos de uma página ou duas! Se você puder adquirir um livro que guia passo a passo como desenvolver um determinado tipo de jogo que esteja tentando fazer agora, esta pode ser uma excelente ideia, pois você aprenderá muito mais por meio da leitura de um livro, que já está organizado para seu aprendizado, do que procurando artigos dispersos na Internet a fim de montar o conhecimento como se fosse um quebra-cabeças;
  • Não baixe livros, compre livros! Tenho percebido que quanto mais livros baixamos, menos lemos! Em contrapartida, um livro comprado em algum momento será lido, tendo em vista o fato de que gastamos dinheiro no mesmo e não queremos “perder aquele dinheiro”, além disso, a leitura de um livro impresso é muito melhor do que a leitura de um livro em um computador;
  • Participação em cursos também pode ser interessante! Cursos possuem uma atuação até mesmo mais direta que o livro, uma vez que passamos a ter um instrutor a nos orientar, a acompanhar os nossos passos;
  • Termine tudo o que você começa! Se você começou a fazer uma clone do Mario e começou a ter muitas dificuldades, continue, desistir somente não é a melhor ideia. Jogos não terminados não contam a seu favor!

A ideia é essa, amigo leitor, e lembre-se: fuja da síndrome do jogo favorito. Apesar de parecer legal em uma primeira instância, você perceberá que algo bem mais gradual o levará realmente a seu objetivo. Pular etapas raramente vale a pena…

Hmmmm… E você, amigo leitor, está com a síndrome do jogo favorito? Deixe-me examiná-lo: abra a boca e diga “ah!”. 🙂

Desenvolvendo Jogos em Delphi


Autor: Christiano Lima Santos

Um grande “olá” a todos!

Demoramos, mas não falhamos em publicar aqui mais um tópico e hoje é a vez de apresentar um pouco do mundo da programação de jogos em Delphi.

Não, não será este um curso completo de programação em Delphi + criação de jogos em Delphi. Acho que está mais para um bate-papo sobre o que pode ser feito com a ferramenta e onde procurar informações que o nortearão neste processo de aprendizagem, ok?

Aos que não conhecem, uma apresentação sobre a ferramenta: Delphi não é uma ferramenta desenvolvida ESPECIFICAMENTE para a criação de jogos. Delphi trata-se de uma IDE (Integrated Development Environment) para a linguagem Object Pascal (os mais xiitas dizem ser uma variação da Object Pascal a linguagem com que Delphi trabalha). É uma ferramenta RAD, ou seja, para o desenvolvimento rápido de sistemas, e talvez isso explique por que esta ferramenta popularizou-se tanto dentre o pessoal de programação.

Por ser uma ferramenta RAD, o desenvolvimento de sistemas tradicionais é feito muito rápido nessa ferramenta, já com jogos, nem tanto, mas também não é nenhum bicho de sete cabeças!

Na verdade, considero o desenvolvimento de jogos em Delphi mais fácil do que em outras linguagens, mas não vou me prolongar mais a fim de evitar atritos desnecessários, como a “guerra das linguagens”.

O Borland Delphi é uma ferramenta paga, mas a Borland lançou o Delphi Explorer, uma versão free de seu software e que pode ser usado livremente.

Você deve estar se perguntando: e o que será que serei capaz de criar em Delphi? Será que há bons jogos desenvolvidos nisso?

Até há!

Um exemplo que já foi muito citado anos atrás são os jogos da série Age of Wonders. Quem quiser conhecer um pouco, pode ver o jogo Age of Wonders 2. Nos sites abaixo (o primeiro é o da empresa desenvolvedora) você poderá encontrar várias informações e telas dele:

http://www.triumphstudios.com/ageofwonders/

http://aow2.heavengames.com/

Um lugar cheio de informações e jogos desenvolvidos em Delphi pode ser encontrado no seguinte site:

http://www.delphigamer.com/main.php

Bem, se você quer criar jogos em Delphi, pode ser uma boa idéia primeiro conhecer a ferramenta, não? Algumas pessoas me perguntam se não há um curso pronto, onde ensine Delphi e desenvolvimento de jogos nesse ambiente. Olha, pode até ter! Se quer em português, o único lugar onde você deve encontrar é a Tilt.net .

Na PDJ nós temos alguns tutoriais, mas nada ensinando o básico de programação em Delphi, então o jeito é ou procurar na Internet (salve Google!) ou correr atrás de alguma empresa/escola que ofereça isso.

Uma vez que você já conhece um pouco a feramenta (aprendeu sobre como ela funciona e fez alguns programas para testar esse aprendizado) você estará apto a começar a pesquisar e estudar sobre a criação de jogos nele.

Uma boa ideia é começar vendo um pouco sobre como desenvolver jogos sem uso de APIs, bibliotecas, etc. voltados ao desenvolvimento de jogos. Por quê? Assim você não se prende aos “vícios” que nos acostumamos quando aprendemos a criar somente com um determinado conjunto de bibliotecas.

A revista ClubeDelphi apresenta esporadicamente artigos e tutoriais sobre criação de jogos, então você pode procurar por edições que sejam do seu interesse. Como já foi citado, a Tilt.net também pode lhe ser de bastante ajuda. Além disso, não se esqueça de nosa querida PDJ.

Você pode encontrar alguns tutoriais sobre jogos em Delphi no seguinte link:

http://www.programadoresdejogos.com/forum/viewtopic.php?t=5758

Se você vai começar estudando desenvolvimento de jogos em Delphi do zero ( o que acho excelente!), você provavelmente vai começar desenhando tudo diretamente no Canvas.

Canvas é uma superfície de um objeto na qual podemos desenhar, por exemplo, quando você coloca uma bitmap para aparecer num TImage, é no canvas do mesmo que ele desenha! Dá para se desenhar no canvas de diversos componentes: TForms, TImages, TPaintbox, etc.
Se você for trabalhar puramente com o Delphi, sem nenhuma biblioteca em especial, experimente brincar de desenhar no canvas do TPaintBox.

O Canvas possui um atributo Pixels, que é um array bidimensional, onde cada ponto representa a cor de um determinado pixel naquele objeto. Pronto! Você precisará mexer com esses pixels para desenhar no canvas.

Desenhe sempre o que vai ficar “por baixo” antes do que vai ficar “por cima”, porque o que você desenha sempre vai cobrir o que já estava lá antes!

Como desenhar um personagem com fundo transparente? Simples! Vamos supor que o preto é a nossa cor transparente… Então para cada ponto que você for desenhar você verifica se aquele pixel é da cor preta, se for, desconsidere-o, caso contrário, pinte no Canvas (plotar um pixel, eis o termo mais usado).

Legal, mas você está querendo criar uma esfera semi-transparente que irá ficar em volta do personagem, dando a impressão de ser um escudo, né? Bem, depois de plotar o seu personagem, você vai, para cada ponto da sua esfera (lembrando de só plotar os que não são parte do fundo!) fazer a média entre a cor que pertence à esfera e a cor que já está na posição em que você vai plotar. Desta forma, você consegue plotar algo com 50% de transparência. Bem, mas você talvez não tenha entendido direito esse cálculo, ou queira que seja plotada a imagem com outro percentual de transparência, então… Vamos a uma rápida fórmula para fazer esse cálculo, ok?
R1,G1,B1 -> são os valores RGB da cor de um dado pixel da esfera
R2,G2,B2 -> são os valores RGB da cor de um dado pixel no canvas
P -> percentual de transparência (0 a esfera não aparece, 100 a esfera aparece sem transparência)
RF,GF,BF -> são os valores RGB da cor que nós plotaremos no pixel
RF = (R1*P + R2*(100-P))/100
GF = (G1*P + G2*(100-P))/100
BF = (B1*P + B2*(100-P))/100
Pronto, ae é só pegar os valores RGB, converter para a cor e jogar nesse pixel!

Agora, você deve perceber que quando for aparecer na tela, ela às vezes ficará piscando. Por que isso? É que enquanto ainda está sendo desenhado no seu PaintBox, o formulário já está sendo desenhado na tela, ae fica mostrando a imagem se formando ainda (flickering ou cintilação, esse é o nome do efeito).
Para resolver isso é só ativar a dupla bufferização nos componentes sendo utilizados. Dependendo de qual o componente usado para desenhar, ativa-se no formulário ou no próprio componente. É só dizer: nome_componente.doublebuffered := true;
Dupla bufferização (ou double buffering) é uma técnica que usa uma superfície auxiliar para desenhar, enquanto que exibe somente a principal. Após concluir o desenho, essas superfícies são trocadas. Assim, o que sempre é visto na tela é uma superfície já totalmente desenhada.

Bem, mas você precisa que tudo isso seja executado infinitamente, num laço. O Delphi te oferece, para isso, um componente Timer. Ajuste o intervalo para que fique razoável a velocidade. Nele você deverá:
1. Verificar quais teclas foram pressionadas;
2. Apagar a tela;
3. Cálculos de colisões, física, etc;
4. Movimentar objetos;
5. Redesenhar a Tela;
6. Validações de vitória, derrota, etc;

Pronto! É algo mais ou menos assim!
Treine bastante a parte de manipulação gráfica e cálculos para detecção de colisão. Após “maestrar” a parte gráfica, cuide da parte sonora.

Como seu objetivo nos primeiros projetos será fazer tudo sem bibliotecas extras, você pode usar o componente MediaPlayer que devem estar em seu Delphi.

Depois de um ou dois projetos completos assim, você deverá ter compreendido as dificuldades que há no desenvolvimento de jogos sem as facilidades das APIs e bibliotecas auxiliares.

Há várias opções para quem está interessado em criar seus jogos em Delphi, algumas delas são:

DelphiX

– Jedi-SDL

– Jedi-DirectX

– GLScene

Eu já usei bastante a DelphiX. Thiago Martinez (W_Snipes) já estudou a GLScene. Enfim, todo mundo que já estudou Delphi para jogos já se envolveu com alguma delas e conhece um pouco de suas vantagens e desvantagens, então querendo conversar sobre, é só falar, ok?

Quando você começar a criar seus jogos, vai perceber que irá precisar de um editor de mapas para criar mais cenários facilmente. Se precisar, pode usar o editor de mapas que eu criei para os meus projetos de jogos 2D tiled. Se bem me lembro, já está com o código-fonte, então você poderá estudá-lo e desenvolver o seu próprio, se preferir.

Bem, como disse, este não é um tutorial. Acho que está mais para um guia falando sobre o que você irá precisar e onde pode encontrar algo sobre. Quem souber tirar proveito pode conseguir com isso um excelente pontapé em seus estudos.

É isso. Até breve!

LuaJava – uma ferramenta de scripting para Java

Autor: Edmar Souza Jr.

Hoje vamos falar sobre como estender a linguagem Java usando a linguagem Lua. Mostraremos o Lua Java e como usá-lo para as principais operações.

Lua

Hoje não estamos aqui para falar do satélite natural da Terra, mas sim da linguagem de scripting Lua. Desenvolvida totalmente em território tupiniquim pelo time da TecGraf (Pontifícia Universidade Católica do Rio de Janeiro – Puc-rio). Lua é leve, veloz, é basicamente procedural, tipada dinamicamente, tem suporte a threads e possúi suporte a Orientação a Objetos usando metamecanismos (LuaTables!!).

Lua já foi empregada com sucesso em vários jogos comerciais, entre eles MDK2, World of Warcraft e Grim Fandango.

Você pode obter mais informações sobre Lua em www.lua.org.
LuaJava

Não, a Nasa não descobriu uma ilha chamada Java na Lua, nem tão pouco os cientistas da ilha de Java estão indo para a Lua. LuaJava é uma biblioteca que permite estender a linguagem Java usando Lua como ferramenta de scripting.

A grande jogada da biblioteca LuaJava é permitir interoperabilidade total entre o ambiente Java e o ambiente Lua. Você pode, por exemplo, criar classes em Lua e usar uma interface para instanceá-las em Java, ou então “importar” uma biblioteca escrita em Java (seja ela criada por você ou do pacote padrão) e usar em seus scripts Lua.
Indo para Lua com Java

A primeira coisa que precisamos para dar início a nossa viagem é do LuaJava, que pode ser adquirido em: http://www.keplerproject.org/luajava/.

Existem dois arquivos necessários para o funcionamento de LuaJava: luajava-x.x.jar e luajava-x.x.dll (libluajava-x.x.so para usuários do Linux)

Para instalar a biblioteca basta copiar o arquivo luajava-x.x.dll para a pasta bin no diretório do seu Java runtime (ou no diretório bin do seu Jdk), o arquivo luajava-x.x.jar deve ficar em algum caminho do CLASSPATH.

Feito isso você estará com o LuaJava instalado e funcionando.

Iniciando o LuaJava

A primeira coisa que você que já programou com Lua em C ou C++ antes deve saber é que as funções da API Lua estão totalmente disponíveis aqui através da classe org.keplerproject.luajava.LuaState. Entretanto, quem não tem intimidade com a API Lua, não fique desesperado. A LuaJava oferece várias funções que facilitam a integração de Lua com Java.

A Classe LuaState

O principal objeto da LuaJava é o LuaState. O LuaState guarda uma referencia para a máquina virtual Lua, e é a partir dele que você vai carregar arquivos de script, registrar classes, chamar funções, etc.

Para iniciar o LuaJava, você deve criar uma nova instância do objeto LuaState. Você pode também opcionalmente abrir as bibliotecas padrão do Lua. O seguinte trecho de código mostra um programa completo que abre uma nova instância da LuaJava e imprime Hello World na tela usando a função print do Lua.

package testeluajava;
import org.keplerproject.luajava.*;
public class Main {
	public static void main(String[] args) {
		LuaState l = LuaStateFactory.newLuaState();
		l.openLibs();
		l.LdoString("print \\"Hello World\\" ");
		l.close();
	}
}

Claro, não precisamos nos fixar a executar comandos com o LdoString. Podemos usar o LdoFile para executar nossos arquivos de Script:

package testeluajava;
import org.keplerproject.luajava.*;
public class Main {
	public static void main(String[] args) {
		LuaState l = LuaStateFactory.newLuaState();
		l.openLibs();
		l.LdoFile("teste.lua");
		l.close();
	}
}

//teste.lua

print "Entre com seu nome:";
local nome = io.read();
local texto = "Hello " .. nome;
print (texto);

O forte do LuaJava como dissemos anteriormente é permitir a interoperabilidade entre o ambiente Lua e o ambiente Java.

Usando classes Java em Lua.

Para usar classes escritas em Java no ambiente Lua, o LuaJava nos fornece duas funções: luajava.bindClass e luajava.new.

A função luajava.bindClass permite importar uma referencia para uma classe escrita dentro do ambiente Java, isso é feito da seguinte maneira:

//teste.lua

JFrame = luajava.bindClass("javax.swing.JFrame");

O único parâmetro que a função bindClass recebe é o nome completo (incluindo os pacotes) para uma classe Java. No exemplo acima JFrame agora é uma referencia para a nossa classe javax.swing.JFrame. Para podermos usar esta referencia para instancear um novo objeto, basta usar a função luajava.new da seguinte maneira:

//teste.lua

c = luajava.new(JFrame);

Após isso, podemos trabalhar com o objeto normalmente como se fosse uma classe nativa do Lua. O código abaixo cria uma janela com o título “Hello PDJ” com 300 x 300 pixels e que encerra a aplicação quando fechada.

//teste.lua

JFrame = luajava.bindClass("javax.swing.JFrame");
f = luajava.new(JFrame);
f:setTitle("Hello PDJ");
f:setSize(300,300);
f:setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f:setVisible(true);

Também podemos importar classes criadas por nós mesmos. Vamos considerar como exemplo a seguinte classe:

//PdjBlog.java

package testeluajava;
import java.util.ArrayList;
public class PdjBlog {
	private ArrayList<String> posts = null;
	public PdjBlog() {
		this.posts= new ArrayList();
	}
	public void newPost(String post) {
		this.posts.add(post);
	}
	public void printPosts() {
		for (int i = 0; i < this.posts.size(); i++) {
			System.out.println(this.posts.get(i));
		}
	}
}

Em Lua podemos usá-la da seguinte maneira:

//teste.lua

PdjBlog = luajava.bindClass("testeluajava.PdjBlog");
blog = luajava.new(PdjBlog);
blog:newPost("Teste Lua Java!!");
blog:newPost("Usando Lua com Java!!");
blog:newPost("Outro Teste Lua Java!!");
blog:printPosts();

Usando classes Lua em Java

Assim como é possível criar classes em Java e usá-las em Lua, também é possível fazer o contrário, definindo classes em Lua e usando-as em Java.

O processo para usar classes Lua em Java já é um pouco mais complicado. Para usar as classes você deve definir ma interface em Java que descreva a classe Lua que você deseja utilizar.

Podemos pegar como exemplo a seguinte interface:

//INpc.java

package testeluajava;
public interface INpc {
	void setNome(String nome);
	void falar();
}

Em Lua esta interface poderia ser definida como a seguinte classe:

//npc.lua

Npc = {
	Nome = "";
	setNome = function(nome)
		Nome = nome;
	end;

	falar= function()
		local texto = "Olá eu sou um npc, meu nome é " .. Nome;
		print (texto);
	end;
}

Para usar esta classe precisamos pegar sua referencia através do método getLuaObject da classe LuaState, como no código a seguir:

LuaObject obj = l.getLuaObject("Npc");

A função getLuaObject recebe um parâmetro que é o Nome do objeto no ambiente Lua, ele retornar uma referencia para esse objeto com o qual podemos trabalhar. Porém ainda não estamos aptos a usar a nossa classe Lua. O LuaObject pode ser qualquer coisa adquirida do ambiente Lua. Podemos por exemplo criar uma função no ambiente Lua e chamá-la do nosso código Java da seguinte maneira:

//teste.lua

function HelloWorld()
	print "Hello world from Lua function";
end;

//Código java

package testeluajava;
import org.keplerproject.luajava.*;
public class Main {
	public static void main(String[] args) {
		LuaState l = LuaStateFactory.newLuaState();
		l.openLibs();
		l.LdoFile("teste.lua");
		try {
			LuaObject func = l.getLuaObject("HelloWorld");
			func.call(null);
		}catch(Exception e) {
			System.out.println(e.getMessage());
		}
		l.close();
	}
}

Voltando a nossa classe npc, para podermos usá-la precisamos criar uma “proxy” para ela, ou seja, precisamos dizer ao LuaJava que a nossa Interface INpc é compatível com nossa classe npc e que podemos usá-la para manipular nosso objeto. Fazemos isso através da função createProxy, como mostrado a seguir:

INpc npc = (INpc) obj.createProxy("testeluajava.INpc");

A função createProxy recebe como parâmetro o nome da Interface que desejamos fazer a Proxy (note que novamente precisamos passar o nome do pacote junto). A função retorna um objeto o qual fazemos casting para INpc. Uma vez feito isso podemos chamar as funções da classe normalmente. Aqui vai a listagem completa do código Java.

package testeluajava;
import org.keplerproject.luajava.*;
public class Main {
	public static void main(String[] args) {
		LuaState l = LuaStateFactory.newLuaState();
		l.openLibs();
		l.LdoFile("npc.lua");
		try {
			LuaObject obj = l.getLuaObject("Npc");
			INpc npc = (INpc) obj.createProxy("testeluajava.INpc");
			npc.setNome("Supersayajin");
			npc.falar();
		}catch(Exception e) {
			System.out.println(e.getMessage());
		}
		l.close();
	}
}

Note que, como estamos lidando com código externo a nossa aplicação é sempre bom tratar possíveis exceções. A função createProxy ainda nos obriga a tratar possíveis LuaException e ClassNotFoundExceptions.

Passando objetos por parâmetro

Quando trabalhamos com proxys chamando classes Lua no ambiente Java não precisamos chamar a função luajava.bindClass para usarmos em Lua uma classe Java que estejamos passando por parâmetro para algum método, a tipagem dinâmica do Lua cuida disso para nós, altere a INpc adicionando um novo método void postarNoBlog(PdjBlog blog); e implemente essa rotina na sua classe em lua:

postarNoBlog = function(blog)
	blog:newPost("Post do Npc ".. Nome);
end;

Quando chamarmos a função postarNoBlog podemos passar para ela um objeto do tipo PdjBlog, sem precisarmos usar a função luajava.bindClass. A seguir segue todo o código fonte para esse exemplo:

//PdjBlog.Java

package testeluajava;
import java.util.ArrayList;
public class PdjBlog {
	private ArrayList<String> posts = null;
	public PdjBlog() {
		this.posts= new ArrayList();
	}
	public void newPost(String post) {
		this.posts.add(post);
	}
	public void printPosts() {
		for (int i = 0; i < this.posts.size(); i++) {
			System.out.println(this.posts.get(i));
		}
	}
}

//INpc.java

package testeluajava;
public interface INpc {
	void setNome(String nome);
	void falar();
	void postarNoBlog(PdjBlog blog);
}

//Main.java

package testeluajava;
import org.keplerproject.luajava.*;
public class Main {
	public static void main(String[] args) {
		LuaState l = LuaStateFactory.newLuaState();
		l.openLibs();
		l.LdoFile("npc.lua");
		try {
			PdjBlog blog = new PdjBlog();
			LuaObject obj = l.getLuaObject("Npc");
			INpc npc = (INpc) obj.createProxy("testeluajava.INpc");
			npc.setNome("Supersayajin");
			npc.postarNoBlog(blog);
			blog.printPosts();
		}catch(Exception e) {
			System.out.println(e.getMessage());
		}
		l.close();
	}
}

//npc.lua

Npc = {
	Nome = "";
	setNome = function(nome)
		Nome = nome;
	end;

	falar = function()
		local texto = "Olá eu sou um npc, meu nome é " .. Nome;
		print (texto);
	end;

	postarNoBlog = function(blog)
		blog:newPost("Post do Npc ".. Nome);
	end;
}

Bom pessoal, esta foi uma pequena introdução ao que é possível fazer com LuaJava. Mais detalhes e tutoriais sobre o LuaJava podem ser conseguidos no site oficial do projeto www.keplerproject.org/luajava

Espero que tenham gostado.

Abraços e até a próxima. 😉

Dando um Zoom em Imagens

Autor: Christiano Lima Santos

Boa noite!

Bem, desta vez, vamos ver como fazer um efeito de zoom para as imagens.

Em primeiro lugar, definamos três coisas:

Zoom -> Efeito de escalonamento proporcional da imagem;
Zoom In -> Efeito de aumento do tamanho da imagem;
Zoom Out -> Efeito de redução do tamanho da imagem.

Seria ridículo se vocês saíssem daqui sem saber isso, né? =)

Bem, agora sim.
Estou falando tudo isso, porque algum tempo atrás estudei os efeitos de Zoom e consegui fazer isso de um jeito bem simples.
O caso é que, dada uma imagem de tamanho largura x altura, nós queremos exibir ela alterada por um determinado fator de zoom centralizada numa outra superficie de tamanho largura x altura.

O que vamos precisar é simplesmente varrer toda a imagem destino (ImgDest) e sair verificando qual a cor do pixel correspondente na imagem origem (ImgOrg).

Agora, a dúvida é: como saber qual o pixel de onde pegar a cor da ImgOrg?

Bem, como a gente falou, a imagem deve ficar centralizada.
Logo o pixel (largura/2, altura/2) de ImgDest deve ser igual ao pixel (largura/2, altura/2) de ImgOrg.

Agora, pensemos juntos. Se eu tenho um pixel de Img que está a uma distância X do centro, ao dobrar a imagem (zoom = 2), a que distância ela estará do centro? 2X.
Do mesmo jeito, se eu reduzir à metade o tamanho da imagem (zoom = 0.5), a que distância ficará? 0.5X.

Viu só? Da ImgOrg para a ImgDest, a distância para o centro fica multiplicada pelo fator zoom.
Mas nós falamos que vamos varrer a ImgDest, ou seja, nós vamos sair de ImgDest para achar valor em ImgOrg, então a gente aplica a operação inversa: divide a distância ao centro por zoom.

Então o que nós vamos ter que fazer é achar a posição relativa de cada pixel ao centro da ImgDest, dividir pelo fator de zoom, somar então novamente o valor do ponto central e então nós teremos achado o pixel correspondente na ImgOrg!

Ae vocês me perguntam… Desse jeito, eu posso pegar um pixel fora da ImgOrg! O que fazer nesse caso?
Simples: o Delphi automaticamente estabelece cor Preta caso o pixel não exista, mas daí vocês podem tratar dentro do código, primeiro verificando se aquele pixel realmente está nos limites, se não estiver, usam uma cor qualquer para plotar na ImgDest.

Ah! E já que vamos trabalhar com divisões, zoom tem que ser diferente de zero!

Bem, o algoritmo no Delphi fica da seguinte forma…

If zoom 0.0 Then
	exit;
for x := 0 to largura-1 do
	for y := 0 to altura-1 do
		ImgDest.Canvas.Pixels[x,y] := ImgOrg.Canvas.Pixels[
											trunc((x - largura/2)/zoom + largura/2),
											trunc((y - altura/2)/zoom + altura/2)];

Viu só como é simples?

Caramba, e eu sempre achando que era bem mais complicado!

Bem, pra concluir, vejam aqui duas imagens exibindo o resultado final…

Essa é a imagem original, vamos agora aplicar a ela um fator de zoom 3 (vamos ter uma imagem resultado correspondente a esse retângulo marcado aí no meio…)

Pronto, aqui está a imagem resultado, lembrando-se que aplicamos um fator de zoom 3.

Então já fica perceptível que para valores absolutos de zoom entre 0 e 1, teremos efeito zoom out (a imagem fica reduzida) e para valores absolutos de zoom maiores que 1, zoom in.

Mas, porque eu falei em valores absolutos?

Simples, porque quando zoom é positivo, a imagem vai ficar normal, mas… quando zoom é negativo, ocorre zoom in/out, mas a imagem final fica invertida (rotacionada 180 graus). Por quê? É só lembrar que nós dividimos por zoom para encontrar o pixel correspondente, nossa origem ( 0, 0 ) é o centro da imagem e, quando for negativo o zoom, irei portanto pegar o pixel do lado oposto da imagem (tanto na horizontal quanto na vertical) .

Bem, é só isso por enquanto, espero que tenham gostado.

Um abraço e até breve!

Grayscale

Autor: Edmar Souza Jr.

O Efeito Grayscale (Escala de cinza)

O efeito escala de cinza, como o próprio nome diz, visa transformar uma imagem colorida em uma imagem com tons de cinza (:P). Este é um efeito bem interessante, pois pode ser usado de diversas maneiras, tanto criando paisagens com ares misteriosos, tanto para servir como a paleta do jogo inteiro.

Como fazer a conversão?

Bom, vou apresentar aki duas técnicas de conversão: A conversão por porcentagem, e a conversão por média. Estas são apenas duas técnicas que eu conheço, mas podem haver mais.

Conversão por média

Este é sem dúvidas o modo mais simples de se fazer, mas também o mais precário. Tudo que fazemos com ele é pegar os valores dos componentes R, G e B e obtermos sua média. Fazemos isso com cada um dos componentes.

O código é o seguinte

r := (ir + ig + ib) div 3;
g := (ir + ig + ib) div 3;
b := (ir + ig + ib) div 3;

cor:= RGB(r,g,b);

ir, ig e ib são valores pegos previamente e representam respectivamente os componentes R, G e B do pixel selecionado. Podemos pegar esses valores usando as funções GetRValue, GetGValue e GetBValue, como no exemplo a seguir:

ir := GetRValue(Origem.Picture.Bitmap.Canvas.Pixels[x, y]);
ig := GetGValue(Origem.Picture.Bitmap.Canvas.Pixels[x, y]);
ib := GetBValue(Origem.Picture.Bitmap.Canvas.Pixels[x, y]);

Nada de mais né?

Entretanto…

Imagine que temos uma imagem dividida em três partes, sendo cada uma preenchida com uma cor diferente, vermelho, verde e azul. O que acontece? Ela vai ficar totalmente cinza. Como resolver isso?

Conversão por porcentagem

Este métódo eh um pouco mais complicado, mas não tanto, tudo o que fazemos é simplesmente usarmos a porcentagem dos componentes. A porcentagem de cada componente pode variar. Vamos ver um exemplo:

r := Trunc(0.3 * ir + 0.59 * ig + 0.11 * ib);
g := Trunc(0.3 * ir + 0.59 * ig + 0.11 * ib);
b := Trunc(0.3 * ir + 0.59 * ig + 0.11 * ib);

Simples certo? Quem me passou esta escala de porcentagem foi o Christiano, de acordo com ele esta é a escala usada pelo Photoshop. Bom, sendo ou não. Ela funciona 😀 e é o que importa.

Com isso, solucionamos o problema mencionado acima, pois estamos trabalhando com a porcentagem de cada componente. E não com a média de seus valores. Note por exemplo, que o resultado da média da cor vermelha, por exemplo, será igual ao resultado da média da cor verde:

Vermelho:

(255 + 0 + 0) / 3 = 85

Verde:

(0 + 255 + 0) / 3 = 85

Essa é a falha que ocorre na primeira técnica. Já na segunda técnica:

Vermelho:

76,5 + 0 + 0 = 76,5

Verde:

0 + 150,45 + 0 = 150,45

Notaram a diferença 😀

Bom, é isso ai e tenham um ótimo dia.

😉