[Resolvido]Utilizando scripts para desenhar

5 respostas
E

Fala galera, depois de um bom tempo distraido com faculdade e principalmente, dota :D , finalmente reiniciei a programação do meu software CG em Java, o UniversoPessoal. Nessa nova versão, estou implementado um sistema de script, que vai usar python.

Me embananei um pouco mas já consegui implementar o Jython e tals, o problema é que no meu programa estou deixando uma linha de comando a principio, pro cara fazer ações simples mesmo. Já criei uma série de comandos simples, que possibilitam fazer as mesmas ações que são feitas com mouse.

Aqui aparece o primeiro problema: eu quero ter a opção de, quando eu apertar seta pra cima, o campo(JtextField) se preencha com último comando que eu digitei. Se eu apertar de novo, que apareça o anterior, e assim por diante. Se eu apertar pra baixo, voltaria os comandos posteriores, que nem numa linha de comando comum como no linux ou no prompt do windows. O problema é que usando action listenner, num sei se isso é possível. Mas por acaso tem outro jeito simples de fazer isso? Minha preocupação é só a interface, porque salvar o que usuário digitar eu sei fazer.

Ai vem o segundo problema. Pra num deixar uma coisa totalmente chata, resolvi criar um script em python mesmo que simularia um jogo de corrida no programa. Desenhar uma pista foi simples, o ruim é fazer com que ela se anime. Tentei usar o código abaixo, mas acontece que o programa inteiro roda e só final exibe o resultado, alguém sabe se eu tenho que usar trheads pra isso funcionar? Ou eu tenho que dar um jetio de usar invoker later e etc no meu action performed? Eis o código:
/**
 * Arquivo onde é armazenado o interpretador de scripts do programa
 */
package br.ericware.programa;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/** Classe responsável por executar todo e qualquer script necessário para execução do programa
 * @author elisson
 *
 */
public class Interpretador implements ActionListener{

	/**
	 * Armazena o módulo 2D
	 */
	private Mod2D mod2D;

	/**
	 * Armazena o desenhista, por onde os desenhos são feitos
	 */
	private Desenhista desenhista;

	/**
	 * Cria a conexão com o interpretador Python
	 */
	private ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");;

	/**
	 * Construtor que recebe como parâmetro o móludo de desenho e o desenhista
	 * @param m2d o módulo2D de onde virão os scripts
	 * @param ds o desenhista do módulo em questão
	 */
	public Interpretador(Mod2D m2d, Desenhista ds) {
		this.mod2D = m2d;
		this.desenhista = ds;
		try {
			engine.eval("from " + Executor.class.getPackage().getName() + " import "+ Executor.class.getSimpleName());

			Set<Class> classes = new HashSet<Class>();

			for (Method metodo : Executor.class.getMethods()) {
				if(Modifier.isPublic( metodo.getModifiers())){
					if(metodo.getName() != "brincar"){
						classes.addAll(Arrays.asList(metodo.getParameterTypes()));
						classes.add(metodo.getReturnType());
						StringBuffer sb =  new StringBuffer("def "+ metodo.getName()+"(");
						for(int i = 0; i < metodo.getParameterTypes().length;i++){
							if(i > 0)
								sb.append(",");
							sb.append("param" + i);

						}
						sb.append("):");
						StringBuffer chamada = new StringBuffer("return "+Executor.class.getSimpleName()+"."+metodo.getName()+"(");
						for(int i = 0; i < metodo.getParameterTypes().length;i++){
							if(i > 0)
								chamada.append(",");
							chamada.append("param" + i);
						}
						chamada.append(")");
						engine.eval(sb.toString()+"\n   "+chamada.toString());
					}else{
						StringBuffer jogo = new StringBuffer("from time import time" +
								"\nvezes = 0" +
								"\ndef brincar():" +
								"\n   global vezes"+
								"\n   comeco = time()" +
								"\n   while(vezes< 6000):" +
								"\n      if((comeco - time()/1000)> 1.5):" +
								"\n         deslocaPista()" +
								"\n         comeco = time()" +
								"\ndef deslocaPista():"+
								"\n   global vezes"+
								"\n   soma = ((vezes%4)*30)" +
								"\n   alterarCorPrimaria(Color.black)" +
								"\n   desenharRetangulo(Point(0,0),Point(400,400))" +
								"\n   alterarCorPrimaria(Color.white)" +
								"\n   desenharRetangulo(Point(185,(-130)+soma),Point(215,(-40)+soma))" +
								"\n   desenharRetangulo(Point(185,0+soma),Point(215,90+soma))" +
								"\n   desenharRetangulo(Point(185,110+soma),Point(215,200+soma))" +
								"\n   desenharRetangulo(Point(185,220+soma),Point(215,310+soma))" +
						"\n   vezes= vezes+1" );
						engine.eval(jogo.toString());
					}
				}
			}
			for(Class classe :classes){
				if(!classe.isPrimitive()){
					engine.eval("from " + classe.getPackage().getName() + " import "+ classe.getSimpleName());
				}
			}
		} catch (ScriptException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub

		JTextField linhaComando =  (JTextField) e.getSource();
		try {
			engine.eval(linhaComando.getText());
		} catch (ScriptException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		linhaComando.setText("");
	}

}
Aqui está a classe Executor
/**
 * Armazena classe responsável pela execução de comandos para o programa 
 */
package br.ericware.programa;

import java.awt.Color;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;

import org.python.antlr.base.mod;

import br.ericware.desenhos.Elipse;
import br.ericware.desenhos.Linha;
import br.ericware.desenhos.Poligono;
import br.ericware.desenhos.Retangulo;
import br.ericware.desenhos.Texto;
import br.ericware.programa.Desenhista.EstadoSelecao;
import br.ericware.programa.Mod2D.NaoSalvouException;


/**Classe responsável por executar os comandos repassados ao programa, não importando a origem
 * 
 * @author elisson
 *
 */
public class Executor {
	
	/**
	 * Armazena a instância única do mod2d para realizar as operações
	 */
	private static Mod2D mod2d;

	/**
	 * Armazena a instância desenhista ligada a instancia de Mod2D armazenada
	 */
	private static Desenhista ds;
	
	/**
	 * Determina qual instância será usada para as operações
	 * @param m2 a instância que será usada para as operações
	 */
	static void setMod2D(Mod2D m2){
		Executor.mod2d = m2;
	}
	
	/**Determina a instância de Desenhista ligado a instância de mod2d armazenada
	 * @param ds o desenhista que deseja-se armazenar
	 */
	static void setDs(Desenhista ds) {
		Executor.ds = ds;
	}
	
	/**
	 * Abre uma imagem a partir do arquivo indicado
	 * @param arquivo caminho do arquivo para abrir a imagem
	 */
	public static void abrirImagem(String arquivo){
		mod2d.giGerenciador.abreImagem(arquivo);
	}
	
	/**
	 * Abre uma imagem a partir do caminho indicado pelo objeto
	 * @param arquivo a instância que apontar para o local onde o caminho está
	 */
	public static void abrirImagem(File arquivo) {
		mod2d.giGerenciador.abreImagem(arquivo);
	}
	
	/**
	 * Cria uma nova imagem nas dimensões padrões
	 */
	public static void criarImagem() {
		mod2d.giGerenciador.novaImagem();
	}
	
	/**
	 * Fecha a imagem indicada
	 * @param img a imagem que se deseja para de editar
	 */
	public static void fecharImagem(Imagem img) {
		mudarImagemEmFoco(img);
		mod2d.giGerenciador.fechaImagemAtual();
	}
	
	/**
	 * Fecha a imagem atual
	 */
	public static void fecharImagemAtual() {
		mod2d.giGerenciador.fechaImagemAtual();
	}
	
	/**
	 * Altera a imagem em foco para imagem indicada
	 * @param novaImagem a imagem que se desejar focar
	 */
	public static void mudarImagemEmFoco(Imagem novaImagem) {		
		mod2d.giGerenciador.modificaImagemFocada(mod2d.giGerenciador.getLsImagens().indexOf(novaImagem));
		
	}
	
	/**
	 * Altera a resolução da imagem atual para a indicada
	 * @param novaAltura a nova altura da imagem
	 * @param novaLargura a nova largura da imagem
	 */
	public static void alterarResolucao(int novaAltura,int novaLargura){
		mod2d.giGerenciador.getImagemAtual().getDesfazerRefazer().addEdit(new AcaoImagem(mod2d.giGerenciador,ds,mod2d.giGerenciador.getImagemAtual(), novaLargura/(float)mod2d.giGerenciador.getImagemAtual().getTamanho().width, novaAltura/(float)mod2d.giGerenciador.getImagemAtual().getTamanho().height));
		mod2d.giGerenciador.getImagemAtual().setTamanho(novaLargura, novaAltura);
		mod2d.giGerenciador.atualizaTitulo();
		ds.invalidar();
		
	}
	
	/**
	 * Altera o nome da imagem atual
	 * @param nome o novo nome que se deseja dar a imagem atual
	 */
	public static void alterarNome(String nome){
		mod2d.giGerenciador.getImagemAtual().setNome(nome);
		mod2d.giGerenciador.atualizaTitulo();
	}
	
	/**
	 * Salva a iamgem indicada
	 * @param img a imagem que se deseja salvar
	 */
	public static void salvarImagem(Imagem img){
		mod2d.giGerenciador.modificaImagemFocada(mod2d.giGerenciador.getLsImagens().indexOf(img));
		try {
			mod2d.giGerenciador.salvarImagemAtual();
		} catch (IOException ioe) {
			// TODO Auto-generated catch block
			ioe.printStackTrace();
		} catch (NaoSalvouException nse) {
			nse.printStackTrace();
		}
	}
	
	/**
	 * Salva a imagem indicada com o nome indicado
	 * @param img a imagem que se deseja salvar
	 * @param arquivo o caminho para o arquivo onde deseja-se salvar a imagem
	 */
	public static void salvarImagem(Imagem img, String arquivo){
		mod2d.giGerenciador.modificaImagemFocada(mod2d.giGerenciador.getLsImagens().indexOf(img));
		try {
			mod2d.giGerenciador.salvarImagemAtual(new File(arquivo));
		} catch (IOException ioe) {
			// TODO Auto-generated catch block
			ioe.printStackTrace();
		} catch (NaoSalvouException nse) {
			nse.printStackTrace();
		}
	}
	
	/**
	 * Retorna a imagem atual
	 * @return a imagem atual
	 */
	public static Imagem retornarImagemAtual(){
		return mod2d.giGerenciador.getImagemAtual();
	}
	
	/**
	 * Fecha o programa
	 */
	public static void fecharPrograma(){
		try {
			mod2d.fecha();
		} catch (NaoSalvouException nse) {
			// TODO Auto-generated catch block
			nse.printStackTrace();
		}
	}
	
	/**
	 * Copia a parte da imagem indicada pelo retangulo
	 * @param retangulo o retangulo da onde a imagem será copiada
	 */
	public static void copiar(Rectangle retangulo){
		Executor.criarSelecao(retangulo);
		mod2d.transfer.copiar(ds);
	}
	
	/**
	 * Colar uma imagem da área de transferencia na área indicada
	 * @param retangulo o retangulo onde a imagem será colada
	 * @param img a imagem que será colada na área indicada
	 */
	public static void colar(Rectangle retangulo, Image	img){
		Executor.criarSelecao(retangulo);
		try {
			mod2d.transfer.colar(ds);
		} catch (UnsupportedFlavorException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * Extrai uma imagem da área indicada
	 * @param retangulo a área da onde a imagem será extraída
	 */
	public static void recortar(Rectangle retangulo){
		Executor.criarSelecao(retangulo);
		mod2d.transfer.recortar(ds);
	}
	
	/**
	 * Altera a cor primária atual para a cor indicada
	 * @param novaCor a nova cor que será aplicada
	 */
	public static void alterarCorPrimaria(Color novaCor){
		mod2d.setCorPrimaria(novaCor);
	}
	
	/**
	 * Altera a cor secundária atual para a cor indicada
	 * @param novaCor a nova cor que será aplicada
	 */
	public static void alterarCorSecundaria(Color novaCor){
		mod2d.setCorSecundaria(novaCor);
	}
	
	/**
	 * Desenha uma linha entre os pontos indicados
	 * @param origem ponto de origem da linha
	 * @param fim ponto de fim da linha
	 */
	public static void desenharLinha(Point origem, Point fim){
		Linha linha = new Linha(origem.x, origem.y, ds.getCorPrimaria());
		linha.setFimX(fim.x).setFimY(fim.y);
		linha.setEspessuraLinha((float) mod2d.getEspessuraAtual());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(linha);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Desenha a elipse tendo como limites os pontos indicados
	 * @param origem um dos pontos que marcará o limite da elipse
	 * @param fim outro ponto que marcará o limite da elipse
	 */
	public static void desenharElipse(Point origem, Point fim){
		Elipse elipse = new Elipse(origem.x, origem.y,fim.x,fim.y, ds.getCorPrimaria());
		elipse.setEspessuraLinha((float) mod2d.getEspessuraAtual());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(elipse);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Cria um circulo a partir do seu centro e raio
	 * @param centro ponto que ser o centro do círculo
	 * @param raio distancia do centro até a borda do circulo
	 */
	public static void desenharCirculo(Point centro, int raio){
		Elipse circulo = new Elipse(centro.x -raio, centro.y - raio,centro.x+raio,centro.y+raio, ds.getCorPrimaria());
		circulo.setEspessuraLinha((float) mod2d.getEspessuraAtual());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(circulo);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Desenha um retangulo limitado pelos pontos indicados
	 * @param origem um ponto que limitará o retângulo
	 * @param fim outro ponto que limitará o retângulo
	 */
	public static void desenharRetangulo(Point origem, Point fim){
		Retangulo retangulo = new Retangulo(origem.x, origem.y,fim.x,fim.y, ds.getCorPrimaria());
		retangulo.setEspessuraLinha((float) mod2d.getEspessuraAtual());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(retangulo);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Cria um texto a partir do ponto indicado
	 * @param origem o ponto que será o canto inferior esquerdo do texto
	 */
	public static void inserirTexto(Point origem){
		Texto texto = new Texto(origem.x, origem.y, mod2d.clCorPrimaria, mod2d.jfJanela, ds);
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(texto);
	}
	
	/**
	 * Cria um texto a partir do texto e ponto indicados
	 * @param origem o ponto onde o texto iniciará
	 * @param texto o texto que será impresso
	 */
	public static void inserirTexto(Point origem, String texto){
		Texto textoImpresso = new Texto(origem.x, origem.y, mod2d.clCorPrimaria, mod2d.jfJanela, ds,texto);
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(textoImpresso);
		ds.finalizaUltimoDesenho();
	}
	
	/**
	 * Indica uma área que será preenchida pela cor de fundo
	 * @param retanguloApagado o retangulo que será pagado
	 */
	public static void apagarArea(Rectangle retanguloApagado){
		Retangulo retangulo = new Retangulo(retanguloApagado.x, retanguloApagado.y,retanguloApagado.x+retanguloApagado.width,retanguloApagado.y+retanguloApagado.height, mod2d.clCorSecundaria);
		retangulo.setEspessuraLinha((float) mod2d.getEspessuraAtual());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(retangulo);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Aplica a ferramenta lata de tinta no ponto indicado
	 * @param ponto o ponto que se deseja preencher os arredores
	 */
	public static void preencherPonto(Point ponto){
		Poligono preenchimento = ds.geraPoligonoPreenchido(ponto.x,ponto.y,ds.getImagem());
		mod2d.giGerenciador.getImagemAtual().getLsDesenhosPendentes().add(preenchimento);
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Cria um novo polígono a partir do ponto indicado
	 * @param origem o ponto que será a origem do polígono
	 */
	public static void iniciarPoligono(Point origem){
	ds.verificaInicioPoligono(origem.x, origem.y);	
	}
	
	/**
	 * Continua a traçar o polígono até o ponto indicado
	 * @param destino o ponto da onde será traçado uma linha que alcançará o atual fim do poligono
	 */
	public static void extenderPoligono(Point destino){
		ds.verificaInicioPoligono(destino.x, destino.y);	
	}
	
	/**
	 * Finaliza o poligno no ponto indicado
	 * @param destino o ultimo ponto do poligono que se deseja traçar
	 */
	public static void finalizarPoligono(Point destino){
		ds.verificaInicioPoligono(destino.x, destino.y);
		finalizarPoligono();
	}
	
	/**
	 * Finaliza o poligono que está sendo desenhado
	 */
	public static void finalizarPoligono(){
		ds.finalizaUltimoDesenho();
		ds.repaint();
	}
	
	/**
	 * Amostra a cor no ponto indicado
	 * @param ponto o ponto da onde se deseja tirar a cor primária
	 */
	public static void amostrarCor(Point ponto){
		ds.amostraCor((int)(ponto.x*mod2d.giGerenciador.getImagemAtual().getZoom()),(int)(ponto.y*mod2d.giGerenciador.getImagemAtual().getZoom()));
	}
	
	/**
	 * Aumenta o zoom
	 */
	public static void aumentarZoom(){
		ds.aumentaZoom();
	}
	
	/**
	 * Diminui o zoom
	 */
	public static void diminuirZoom(){
		ds.diminuiZoom();
	}
	
	/**
	 * Determina o zoom
	 * @param zoom O valor em porcentagem qeu se deseja para o novo zoom
	 */
	public static void aplicarZoom(int zoom){
		ds.setZoom(((double)(zoom))/100.0);
	}
	
	/**
	 * Altera a espessura da ferramenta atual
	 * @param espessura a nova espessura desejada
	 */
	public static void alterarExpessura(double espessura){
		mod2d.setEspessuraAtual(espessura);
	}
	
	/**
	 * Troca a ferramenta atualmente usada pela indicada por seu nome
	 * @param ferramenta o nome da ferramenta desejada
	 */
	public static void trocarFerramenta(String ferramenta){
		Enumeration<AbstractButton> botoes = mod2d.bgFerramentas.getElements();
		while(botoes.hasMoreElements()){
			AbstractButton botao = botoes.nextElement();
			if(botao.getName() == ferramenta){
				ButtonModel modelo = botao.getModel();
				mod2d.bgFerramentas.setSelected(modelo, true);
			}
		}
	}
	
	/**
	 * Inicia um joguinho de corrida :)
	 */
	public static void brincar(){
		
	}
	
	/**
	 * Rotaciona a imagem no sentido horário
	 */
	public static void rotacionar(){
		mod2d.giGerenciador.getImagemAtual().rotacionar();
	}
	
	/**
	 * Desfaz a última ação realizada na imagem atual
	 */
	public static void desfazer(){
		if(mod2d.giGerenciador.getImagemAtual().getDesfazerRefazer().canUndo())
			mod2d.giGerenciador.getImagemAtual().getDesfazerRefazer().undo();
	}
	
	/**
	 * Refaz a última ação desfeita na imagem
	 */
	public static void refazer(){
		if(mod2d.giGerenciador.getImagemAtual().getDesfazerRefazer().canRedo()){
			mod2d.giGerenciador.getImagemAtual().getDesfazerRefazer().redo();
		}
	}
	
	/**
	 * Cria uma seleção na área do retangulo indicado. Entretano, a seleção só será exibida se a ferramenta seleciona for seleção
	 * @param area o retangulo onde ficará a seleção
	 */
	public static void criarSelecao(Rectangle area){
		mod2d.setSelecao(area);
	}
}
Uma ajuda pra qualquer um dos problema é muito bem vinda, Agradeço desde já.

5 Respostas

V

Eu tive muito menos problemas com o Groovy, por isso acabei abandonando o Jython.

Para fazer o editor de textos, você deve:

  1. Usar listeners se a funcionalidade só funcionar quando vc estiver com o cursor sobre o editor;
  2. Usar ActionMap e Keymap para ela funcionar caso ele aperte as setas em qualquer local da dele (não interessando onde esteja o foco).

Para a parte de animação, sim, é necessário usar threads. Alguns tutoriais de Java2D do Ponto V cobrem exclusivamente essa parte:
http://pontov.com.br/site/java/48-java2d/121-o-loop-de-animacao
http://pontov.com.br/site/java/48-java2d/123-a-primeira-animacao
http://pontov.com.br/site/java/48-java2d/124-desenho-direto-active-rendering

E parabéns pelo seu editor, ficou muito bacana.

E

Valeu cara, dei uma olhada melhor em concorrência e com o código abaixo consegui fazer a “pista” se mover. Só falta agora criar o carro , os obstáculos, e fazer com que o python reconheça os eventos de teclas(python parece que nem tem listenners :frowning: ).

StringBuffer jogo = new StringBuffer("import time" +
								"\nimport thread" +
								"\nvezes = 0" +
								"\ndef brincar():" +
								"\n    thread.start_new_thread(deslocaPista,())" +
								"\ndef deslocaPista():"+
								"\n   global vezes"+
								"\n   while(vezes< 6000):" +
								"\n      soma = ((vezes%4)*30)" +
								"\n      alterarCorPrimaria(Color.black)" +
								"\n      desenharRetangulo(Point(0,0),Point(400,400))" +
								"\n      alterarCorPrimaria(Color.white)" +
								"\n      desenharRetangulo(Point(185,(-130)+soma),Point(215,(-40)+soma))" +
								"\n      desenharRetangulo(Point(185,0+soma),Point(215,90+soma))" +
								"\n      desenharRetangulo(Point(185,110+soma),Point(215,200+soma))" +
								"\n      desenharRetangulo(Point(185,220+soma),Point(215,310+soma))" +
								"\n      time.sleep(0.3)" +
						"\n      vezes= vezes+1" );
						engine.eval(jogo.toString());

Vou ter criar um keypressed então mesmo pro text box num é, beleza, só queria saber mesmo.

É interessante como eu olhava praqueles métodos de concorrência na api padrão e num via importância na maioria deles. Foi só eu ativar esse código ai que já começo a parecer de um monte de exceção randômica, dizendo que minha lista tava sendo alterada por uma thead que não a criou, que tinha nullpointer em algumas cores.

Outra coisa óbvia também foi o flirck gigantesco, mesmo num código tão simples.

Lendo os comentários do artigo do viny, vi com um certo pesar que java é fraco em tudo que meu programa vai se basear a longo prazo: 3D, sons e jogos. Pelo jeito vai ter que sair tudo na mão mesmo(aidna bem que não conto com isso pra me alimentar). Quem em 2020 eu tenha feito algo concreto e maduro, vamo ver né.

E

Bem galera, resolvido os dois problemas o código final fico assim:

/**
 * Arquivo onde é armazenado o interpretador de scripts do programa
 */
package br.ericware.programa;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Set;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/** Classe responsável por executar todo e qualquer script necessário para execução do programa
 * @author elisson
 *
 */
public class Interpretador implements ActionListener, KeyListener{

	/**
	 * Armazena o módulo 2D
	 */
	private Mod2D mod2D;

	/**
	 * Armazena o desenhista, por onde os desenhos são feitos
	 */
	private Desenhista desenhista;

	/**
	 * Armazena todo um histórico de comandos
	 */
	private LinkedList<String> comandos = new LinkedList<String>();
	
	/**
	 * Cria a conexão com o interpretador Python
	 */
	private ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");

	/**
	 * Armazena a atual posição do historico
	 */
	private ListIterator<String> historico = comandos.listIterator();
	
	/**
	 * Armazena o que foi digitado na linha de comando
	 */
	private String linhaAtual;
	
	/**
	 * Construtor que recebe como parâmetro o móludo de desenho e o desenhista
	 * @param m2d o módulo2D de onde virão os scripts
	 * @param ds o desenhista do módulo em questão
	 */
	public Interpretador(Mod2D m2d, Desenhista ds) {
		this.mod2D = m2d;
		this.desenhista = ds;
		try {
			engine.eval("from " + Executor.class.getPackage().getName() + " import "+ Executor.class.getSimpleName());

			Set<Class> classes = new HashSet<Class>();

			for (Method metodo : Executor.class.getMethods()) {
				if(Modifier.isPublic( metodo.getModifiers())){
					if(metodo.getName() != "brincar"){
						classes.addAll(Arrays.asList(metodo.getParameterTypes()));
						classes.add(metodo.getReturnType());
						StringBuffer sb =  new StringBuffer("def "+ metodo.getName()+"(");
						for(int i = 0; i < metodo.getParameterTypes().length;i++){
							if(i > 0)
								sb.append(",");
							sb.append("param" + i);

						}
						sb.append("):");
						StringBuffer chamada = new StringBuffer("return "+Executor.class.getSimpleName()+"."+metodo.getName()+"(");
						for(int i = 0; i < metodo.getParameterTypes().length;i++){
							if(i > 0)
								chamada.append(",");
							chamada.append("param" + i);
						}
						chamada.append(")");
						engine.eval(sb.toString()+"\n   "+chamada.toString());
					}else{
						StringBuffer jogo = new StringBuffer("\nfrom javax.swing import SwingUtilities" +
								"\nimport sys,random,threading,thread,time,math" +
								"\ndeslocamento = 0" +
								"\ndef mover(direcao):" +
								"\n   global deslocamento" +
								"\n   if(direcao == 'Left'):" +
								"\n      if(deslocamento>-200):" +
								"\n         deslocamento -= 10" +
								"\n   elif(direcao == 'Right'):" +
								"\n      if(deslocamento<200):" +
								"\n         deslocamento += 10" +
								"\ndef brincar():" +
								"\n   thread.start_new_thread(deslocaPista,())" +
								"\nobstaculos = [[0,random.randint(0, 400)],[0,random.randint(0, 400)]]" +
								"\ndef desenhaObs():" +
								"\n   global obstaculos" +
								"\n   alterarCorPrimaria(Color.orange)" +
								"\n   for obs in obstaculos:" +
								"\n      desenharCirculo(Point(obs[1],obs[0]),30)" +
								"\ndef deslocaObs():" +
								"\n   global obstaculos" +
								"\n   for obs in obstaculos:" +
								"\n      obs[0] = obs[0] +25" +
								"\ndef reiniciaObs():" +
								"\n   global obstaculos" +
								"\n   for obs in obstaculos:" +
								"\n      if(obs[0]>400):" +
								"\n         obs[0] = 0" +
								"\n         obs[1] = random.randint(0, 400)" +
								"\ndef detectaColisao():" +
								"\n   global obstaculos" +
								"\n   global deslocamento"+
								"\n   for obs in obstaculos:" +
								"\n      if(obs[0]<330):" +
								"\n         continue" +
								"\n      distx1 = (obs[1])-(deslocamento+250)" +
								"\n      distx2 = (150+deslocamento) - (obs[1])" +
								"\n      print distx1,distx2" +
								"\n      if(distx1<30 and distx2<30):" +
								"\n         if(distx1>0 and math.sqrt(distx1**2+(360 - obs[0])**2)<30):" +
								"\n            inserirTexto(Point(130,200),'Você perdeu!HA! HA!')" +
								"\n            sys.exit(0)" +
								"\n         elif(distx2>0  and math.sqrt(distx2**2+(360 - obs[0])**2)<30):" +
								"\n            inserirTexto(Point(130,200),'Você perdeu!HA! HA!')" +
								"\n            sys.exit(0)" +
								"\n         elif(distx1<0 and distx2<0):" +
								"\n            inserirTexto(Point(130,200),'Você perdeu!HA! HA!')" +
								"\n            sys.exit(0)" +
								"\ndef deslocaPista():" +
								"\n   global deslocamento"+
								"\n   vezes = 0"+
								"\n   while(vezes< 570):" +
								"\n      soma = ((vezes%4)*25)" +
								"\n      reiniciaObs()" +
								"\n      alterarCorPrimaria(Color.black)" +
								"\n      desenharRetangulo(Point(0,0),Point(400,400))" +
								"\n      alterarCorPrimaria(Color.white)" +
								"\n      desenharRetangulo(Point(185,-95+soma),Point(215,-10+soma))" +
								"\n      desenharRetangulo(Point(185,(305)+soma),Point(215,(390)+soma))" +
								"\n      desenharRetangulo(Point(185,5+soma),Point(215,90+soma))" +
								"\n      desenharRetangulo(Point(185,105+soma),Point(215,190+soma))" +
								"\n      desenharRetangulo(Point(185,205+soma),Point(215,290+soma))" +
								"\n      alterarCorPrimaria(Color.red)" +
								"\n      desenharRetangulo(Point(150+deslocamento,360),Point(250+deslocamento,400))" +
								"\n      desenhaObs()" +
								"\n      detectaColisao()" +
								"\n      deslocaObs()" +
								"\n      time.sleep(0.3-((vezes//30)/20))" +
								"\n      " +
						"\n      vezes= vezes+1" +
						"\n   inserirTexto(Point(130,200),'Você zerou!!!!!')" );
						engine.eval(jogo.toString());
					}
				}
			}
			for(Class classe :classes){
				if(!classe.isPrimitive()){
					engine.eval("from " + classe.getPackage().getName() + " import "+ classe.getSimpleName());
				}
			}
		} catch (ScriptException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub

		JTextField linhaComando =  (JTextField) e.getSource();
		try {
			engine.eval(linhaComando.getText());
		} catch (ScriptException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(!linhaComando.getText().equals(comandos.peekLast())){
			comandos.add(linhaComando.getText());
			historico = comandos.listIterator(comandos.size());
		}
		linhaComando.setText("");
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		JTextField linhaComando =  (JTextField) arg0.getSource();
		if(arg0.getKeyCode() == KeyEvent.VK_UP){
			if(historico.hasPrevious()){
				if(!historico.hasNext())
					linhaAtual = linhaComando.getText();
				linhaComando.setText(historico.previous());
			}
		}else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){
			if(historico.hasNext())
				linhaComando.setText(historico.next());
			else
				linhaComando.setText(linhaAtual);
		}else if(!arg0.isActionKey()){
			historico = comandos.listIterator(comandos.size());
		}
		try {
			engine.eval("\nmover('"+KeyEvent.getKeyText(arg0.getKeyCode())+"')");
		} catch (ScriptException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

}

O flirck lógico só aumento, ms um futuro eu eleimino esse problema, valeu pela ajuda.

V

Para eliminar o flickering, você deve usar Double Buffering.

No Java, há duas formas de fazer isso:

  1. Criar uma BufferedImage com o desenho da tela pronto (FrontBuffer), e outra de trabalho (BackBuffer). Você desenha no BackBuffer e, quando a pintura for concluída, substitui o FrontBuffer pelo BackBuffer e cria uma nova BufferedImage para o BackBuffer.

Se quiser evitar ficar criando e destruindo BufferedImages, você pode troca-las ao invés de descartar a de pintura.

Se você estiver chamando constantemente o método de pintura, o processo pode ser simplificado, pois pode deixar a própria janela como FrontBuffer e usar só uma imagem auxiliar no método paint. Basta então criar uma BufferedImage do tamanho da tela no início do paint, desenhar nessa BufferedImage, e ao final do paint desenhar essa imagem na tela. Um exemplo dessa técnica pode ser visto aqui: http://www.guj.com.br/java/128713-jframe-com-imagem-em-fade#1165351

  1. Usar renderização ativa, através da classe BufferStrategy. Essa técnica é explicada aqui:
    http://pontov.com.br/site/java/48-java2d/124-desenho-direto-active-rendering
E

Legal essa explicação, mas não vou implementar agora, porque o objetivo do script é mostrar como com a linha de comando, se pode fazer várias coisas. Quero primeiro estabelecer o módulo de desenho como algo mais sólido. Depois, vou torná-lo um módulo do programa. Ai sim eu crio o módulo de animação, de modulação 3D, de edição de som, de animação 3D, etc. Por hora fica assim mesmo.

Ah, pra quem quer testar como ficou:
https://sourceforge.net/projects/universopessoal/files/latest/download?source=files

Criado 8 de abril de 2012
Ultima resposta 12 de abr. de 2012
Respostas 5
Participantes 2